Merge "Fix possible infinite loop when purging textures."
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 50bee9c..e5f1f90 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -79,6 +79,8 @@
 $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/android/os/storage/*)
 $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/android/content/IClipboard.P)
 $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/telephony/java/com/android/internal/telephony/ITelephonyRegistry.P)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/android_stubs_current_intermediates)
+$(call add-clean-step, rm -rf out/target/common/docs/api-stubs*)
 
 # ************************************************
 # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
diff --git a/api/current.xml b/api/current.xml
index eb21d97..bfbeaa2 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -4200,6 +4200,17 @@
  visibility="public"
 >
 </field>
+<field name="filterTouchesWhenObscured"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843460"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="finishOnCloseSystemDialogs"
  type="int"
  transient="false"
@@ -6158,50 +6169,6 @@
  visibility="public"
 >
 </field>
-<field name="kraken_resource_pad61"
- type="int"
- transient="false"
- volatile="false"
- value="16843460"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="kraken_resource_pad62"
- type="int"
- transient="false"
- volatile="false"
- value="16843459"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="kraken_resource_pad63"
- type="int"
- transient="false"
- volatile="false"
- value="16843458"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="kraken_resource_pad64"
- type="int"
- transient="false"
- volatile="false"
- value="16843457"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
 <field name="kraken_resource_pad7"
  type="int"
  transient="false"
@@ -16482,6 +16449,50 @@
  visibility="public"
 >
 </field>
+<field name="TextAppearance_StatusBar_EventContent"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973927"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TextAppearance_StatusBar_EventContent_Title"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973928"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TextAppearance_StatusBar_Icon"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973926"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TextAppearance_StatusBar_Title"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973925"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="TextAppearance_Theme"
  type="int"
  transient="false"
@@ -17824,50 +17835,6 @@
  visibility="public"
 >
 </field>
-<field name="kraken_resource_pad41"
- type="int"
- transient="false"
- volatile="false"
- value="16973928"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="kraken_resource_pad42"
- type="int"
- transient="false"
- volatile="false"
- value="16973927"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="kraken_resource_pad43"
- type="int"
- transient="false"
- volatile="false"
- value="16973926"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="kraken_resource_pad44"
- type="int"
- transient="false"
- volatile="false"
- value="16973925"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
 <field name="kraken_resource_pad5"
  type="int"
  transient="false"
@@ -19810,7 +19777,7 @@
 </package>
 <package name="android.animation"
 >
-<class name="Animatable"
+<class name="Animator"
  extends="java.lang.Object"
  abstract="true"
  static="false"
@@ -19820,8 +19787,8 @@
 >
 <implements name="java.lang.Cloneable">
 </implements>
-<constructor name="Animatable"
- type="android.animation.Animatable"
+<constructor name="Animator"
+ type="android.animation.Animator"
  static="false"
  final="false"
  deprecated="not deprecated"
@@ -19838,7 +19805,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="listener" type="android.animation.Animatable.AnimatableListener">
+<parameter name="listener" type="android.animation.Animator.AnimatorListener">
 </parameter>
 </method>
 <method name="cancel"
@@ -19853,7 +19820,7 @@
 >
 </method>
 <method name="clone"
- return="android.animation.Animatable"
+ return="android.animation.Animator"
  abstract="false"
  native="false"
  synchronized="false"
@@ -19886,7 +19853,7 @@
 >
 </method>
 <method name="getListeners"
- return="java.util.ArrayList&lt;android.animation.Animatable.AnimatableListener&gt;"
+ return="java.util.ArrayList&lt;android.animation.Animator.AnimatorListener&gt;"
  abstract="false"
  native="false"
  synchronized="false"
@@ -19939,7 +19906,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="listener" type="android.animation.Animatable.AnimatableListener">
+<parameter name="listener" type="android.animation.Animator.AnimatorListener">
 </parameter>
 </method>
 <method name="setDuration"
@@ -20028,7 +19995,7 @@
 >
 </method>
 </class>
-<interface name="Animatable.AnimatableListener"
+<interface name="Animator.AnimatorListener"
  abstract="true"
  static="true"
  final="false"
@@ -20045,7 +20012,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="animation" type="android.animation.Animatable">
+<parameter name="animation" type="android.animation.Animator">
 </parameter>
 </method>
 <method name="onAnimationEnd"
@@ -20058,7 +20025,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="animation" type="android.animation.Animatable">
+<parameter name="animation" type="android.animation.Animator">
 </parameter>
 </method>
 <method name="onAnimationRepeat"
@@ -20071,7 +20038,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="animation" type="android.animation.Animatable">
+<parameter name="animation" type="android.animation.Animator">
 </parameter>
 </method>
 <method name="onAnimationStart"
@@ -20084,11 +20051,11 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="animation" type="android.animation.Animatable">
+<parameter name="animation" type="android.animation.Animator">
 </parameter>
 </method>
 </interface>
-<class name="AnimatableInflater"
+<class name="AnimatorInflater"
  extends="java.lang.Object"
  abstract="false"
  static="false"
@@ -20096,16 +20063,16 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<constructor name="AnimatableInflater"
- type="android.animation.AnimatableInflater"
+<constructor name="AnimatorInflater"
+ type="android.animation.AnimatorInflater"
  static="false"
  final="false"
  deprecated="not deprecated"
  visibility="public"
 >
 </constructor>
-<method name="loadAnimatable"
- return="android.animation.Animatable"
+<method name="loadAnimator"
+ return="android.animation.Animator"
  abstract="false"
  native="false"
  synchronized="false"
@@ -20122,7 +20089,7 @@
 </exception>
 </method>
 </class>
-<class name="AnimatableListenerAdapter"
+<class name="AnimatorListenerAdapter"
  extends="java.lang.Object"
  abstract="true"
  static="false"
@@ -20130,10 +20097,10 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<implements name="android.animation.Animatable.AnimatableListener">
+<implements name="android.animation.Animator.AnimatorListener">
 </implements>
-<constructor name="AnimatableListenerAdapter"
- type="android.animation.AnimatableListenerAdapter"
+<constructor name="AnimatorListenerAdapter"
+ type="android.animation.AnimatorListenerAdapter"
  static="false"
  final="false"
  deprecated="not deprecated"
@@ -20150,7 +20117,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="animation" type="android.animation.Animatable">
+<parameter name="animation" type="android.animation.Animator">
 </parameter>
 </method>
 <method name="onAnimationEnd"
@@ -20163,7 +20130,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="animation" type="android.animation.Animatable">
+<parameter name="animation" type="android.animation.Animator">
 </parameter>
 </method>
 <method name="onAnimationRepeat"
@@ -20176,7 +20143,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="animation" type="android.animation.Animatable">
+<parameter name="animation" type="android.animation.Animator">
 </parameter>
 </method>
 <method name="onAnimationStart"
@@ -20189,77 +20156,28 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="animation" type="android.animation.Animatable">
+<parameter name="animation" type="android.animation.Animator">
 </parameter>
 </method>
 </class>
-<class name="Animator"
- extends="android.animation.Animatable"
+<class name="AnimatorSet"
+ extends="android.animation.Animator"
  abstract="false"
  static="false"
- final="false"
+ final="true"
  deprecated="not deprecated"
  visibility="public"
 >
-<constructor name="Animator"
- type="android.animation.Animator"
+<constructor name="AnimatorSet"
+ type="android.animation.AnimatorSet"
  static="false"
  final="false"
  deprecated="not deprecated"
  visibility="public"
 >
 </constructor>
-<constructor name="Animator"
- type="android.animation.Animator"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="duration" type="long">
-</parameter>
-<parameter name="values" type="T...">
-</parameter>
-</constructor>
-<method name="addUpdateListener"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="listener" type="android.animation.Animator.AnimatorUpdateListener">
-</parameter>
-</method>
-<method name="getAnimatedValue"
- return="java.lang.Object"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="getAnimatedValue"
- return="java.lang.Object"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="propertyName" type="java.lang.String">
-</parameter>
-</method>
-<method name="getCurrentPlayTime"
- return="long"
+<method name="getChildAnimations"
+ return="java.util.ArrayList&lt;android.animation.Animator&gt;"
  abstract="false"
  native="false"
  synchronized="false"
@@ -20280,50 +20198,6 @@
  visibility="public"
 >
 </method>
-<method name="getFrameDelay"
- return="long"
- abstract="false"
- native="false"
- synchronized="false"
- static="true"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="getInterpolator"
- return="android.view.animation.Interpolator"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="getRepeatCount"
- return="int"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="getRepeatMode"
- return="int"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
 <method name="getStartDelay"
  return="long"
  abstract="false"
@@ -20335,17 +20209,6 @@
  visibility="public"
 >
 </method>
-<method name="getValues"
- return="android.animation.PropertyValuesHolder[]"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
 <method name="isRunning"
  return="boolean"
  abstract="false"
@@ -20357,8 +20220,8 @@
  visibility="public"
 >
 </method>
-<method name="removeUpdateListener"
- return="void"
+<method name="play"
+ return="android.animation.AnimatorSet.Builder"
  abstract="false"
  native="false"
  synchronized="false"
@@ -20367,10 +20230,10 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="listener" type="android.animation.Animator.AnimatorUpdateListener">
+<parameter name="anim" type="android.animation.Animator">
 </parameter>
 </method>
-<method name="reverse"
+<method name="playSequentially"
  return="void"
  abstract="false"
  native="false"
@@ -20380,8 +20243,10 @@
  deprecated="not deprecated"
  visibility="public"
 >
+<parameter name="items" type="android.animation.Animator...">
+</parameter>
 </method>
-<method name="setCurrentPlayTime"
+<method name="playTogether"
  return="void"
  abstract="false"
  native="false"
@@ -20391,7 +20256,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="playTime" type="long">
+<parameter name="items" type="android.animation.Animator...">
 </parameter>
 </method>
 <method name="setDuration"
@@ -20407,32 +20272,6 @@
 <parameter name="duration" type="long">
 </parameter>
 </method>
-<method name="setEvaluator"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="value" type="android.animation.TypeEvaluator">
-</parameter>
-</method>
-<method name="setFrameDelay"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="true"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="frameDelay" type="long">
-</parameter>
-</method>
 <method name="setInterpolator"
  return="void"
  abstract="false"
@@ -20443,33 +20282,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="value" type="android.view.animation.Interpolator">
-</parameter>
-</method>
-<method name="setRepeatCount"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="value" type="int">
-</parameter>
-</method>
-<method name="setRepeatMode"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="value" type="int">
+<parameter name="interpolator" type="android.view.animation.Interpolator">
 </parameter>
 </method>
 <method name="setStartDelay"
@@ -20485,76 +20298,18 @@
 <parameter name="startDelay" type="long">
 </parameter>
 </method>
-<method name="setValues"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="values" type="android.animation.PropertyValuesHolder...">
-</parameter>
-</method>
-<method name="setValues"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="values" type="T...">
-</parameter>
-</method>
-<field name="INFINITE"
- type="int"
- transient="false"
- volatile="false"
- value="-1"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="RESTART"
- type="int"
- transient="false"
- volatile="false"
- value="1"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="REVERSE"
- type="int"
- transient="false"
- volatile="false"
- value="2"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
 </class>
-<interface name="Animator.AnimatorUpdateListener"
- abstract="true"
- static="true"
+<class name="AnimatorSet.Builder"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
  final="false"
  deprecated="not deprecated"
  visibility="public"
 >
-<method name="onAnimationUpdate"
+<method name="after"
  return="void"
- abstract="true"
+ abstract="false"
  native="false"
  synchronized="false"
  static="false"
@@ -20562,10 +20317,49 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="animation" type="android.animation.Animator">
+<parameter name="anim" type="android.animation.Animator">
 </parameter>
 </method>
-</interface>
+<method name="after"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="delay" type="long">
+</parameter>
+</method>
+<method name="before"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="anim" type="android.animation.Animator">
+</parameter>
+</method>
+<method name="with"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="anim" type="android.animation.Animator">
+</parameter>
+</method>
+</class>
 <class name="DoubleEvaluator"
  extends="java.lang.Object"
  abstract="false"
@@ -20922,8 +20716,8 @@
 <parameter name="child" type="android.view.View">
 </parameter>
 </method>
-<method name="getAnimatable"
- return="android.animation.Animatable"
+<method name="getAnimator"
+ return="android.animation.Animator"
  abstract="false"
  native="false"
  synchronized="false"
@@ -21011,7 +20805,7 @@
 <parameter name="listener" type="android.animation.LayoutTransition.TransitionListener">
 </parameter>
 </method>
-<method name="setAnimatable"
+<method name="setAnimator"
  return="void"
  abstract="false"
  native="false"
@@ -21023,7 +20817,7 @@
 >
 <parameter name="transitionType" type="int">
 </parameter>
-<parameter name="animatable" type="android.animation.Animatable">
+<parameter name="animator" type="android.animation.Animator">
 </parameter>
 </method>
 <method name="setDuration"
@@ -21190,24 +20984,24 @@
 </parameter>
 </method>
 </interface>
-<class name="PropertyAnimator"
- extends="android.animation.Animator"
+<class name="ObjectAnimator"
+ extends="android.animation.ValueAnimator"
  abstract="false"
  static="false"
  final="true"
  deprecated="not deprecated"
  visibility="public"
 >
-<constructor name="PropertyAnimator"
- type="android.animation.PropertyAnimator"
+<constructor name="ObjectAnimator"
+ type="android.animation.ObjectAnimator"
  static="false"
  final="false"
  deprecated="not deprecated"
  visibility="public"
 >
 </constructor>
-<constructor name="PropertyAnimator"
- type="android.animation.PropertyAnimator"
+<constructor name="ObjectAnimator"
+ type="android.animation.ObjectAnimator"
  static="false"
  final="false"
  deprecated="not deprecated"
@@ -21222,8 +21016,8 @@
 <parameter name="values" type="T...">
 </parameter>
 </constructor>
-<constructor name="PropertyAnimator"
- type="android.animation.PropertyAnimator"
+<constructor name="ObjectAnimator"
+ type="android.animation.ObjectAnimator"
  static="false"
  final="false"
  deprecated="not deprecated"
@@ -21450,206 +21244,6 @@
 </parameter>
 </method>
 </class>
-<class name="Sequencer"
- extends="android.animation.Animatable"
- abstract="false"
- static="false"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-<constructor name="Sequencer"
- type="android.animation.Sequencer"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</constructor>
-<method name="getChildAnimations"
- return="java.util.ArrayList&lt;android.animation.Animatable&gt;"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="getDuration"
- return="long"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="getStartDelay"
- return="long"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="isRunning"
- return="boolean"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="play"
- return="android.animation.Sequencer.Builder"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="anim" type="android.animation.Animatable">
-</parameter>
-</method>
-<method name="playSequentially"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="sequenceItems" type="android.animation.Animatable...">
-</parameter>
-</method>
-<method name="playTogether"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="sequenceItems" type="android.animation.Animatable...">
-</parameter>
-</method>
-<method name="setDuration"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="duration" type="long">
-</parameter>
-</method>
-<method name="setInterpolator"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="interpolator" type="android.view.animation.Interpolator">
-</parameter>
-</method>
-<method name="setStartDelay"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="startDelay" type="long">
-</parameter>
-</method>
-</class>
-<class name="Sequencer.Builder"
- extends="java.lang.Object"
- abstract="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<method name="after"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="anim" type="android.animation.Animatable">
-</parameter>
-</method>
-<method name="after"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="delay" type="long">
-</parameter>
-</method>
-<method name="before"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="anim" type="android.animation.Animatable">
-</parameter>
-</method>
-<method name="with"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="anim" type="android.animation.Animatable">
-</parameter>
-</method>
-</class>
 <interface name="TypeEvaluator"
  abstract="true"
  static="false"
@@ -21675,6 +21269,379 @@
 </parameter>
 </method>
 </interface>
+<class name="ValueAnimator"
+ extends="android.animation.Animator"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="ValueAnimator"
+ type="android.animation.ValueAnimator"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<constructor name="ValueAnimator"
+ type="android.animation.ValueAnimator"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="duration" type="long">
+</parameter>
+<parameter name="values" type="T...">
+</parameter>
+</constructor>
+<method name="addUpdateListener"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="listener" type="android.animation.ValueAnimator.AnimatorUpdateListener">
+</parameter>
+</method>
+<method name="getAnimatedValue"
+ return="java.lang.Object"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getAnimatedValue"
+ return="java.lang.Object"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="propertyName" type="java.lang.String">
+</parameter>
+</method>
+<method name="getCurrentPlayTime"
+ return="long"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getDuration"
+ return="long"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getFrameDelay"
+ return="long"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getInterpolator"
+ return="android.view.animation.Interpolator"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getRepeatCount"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getRepeatMode"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getStartDelay"
+ return="long"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getValues"
+ return="android.animation.PropertyValuesHolder[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="isRunning"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="removeUpdateListener"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="listener" type="android.animation.ValueAnimator.AnimatorUpdateListener">
+</parameter>
+</method>
+<method name="reverse"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="setCurrentPlayTime"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="playTime" type="long">
+</parameter>
+</method>
+<method name="setDuration"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="duration" type="long">
+</parameter>
+</method>
+<method name="setEvaluator"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="value" type="android.animation.TypeEvaluator">
+</parameter>
+</method>
+<method name="setFrameDelay"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="frameDelay" type="long">
+</parameter>
+</method>
+<method name="setInterpolator"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="value" type="android.view.animation.Interpolator">
+</parameter>
+</method>
+<method name="setRepeatCount"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="value" type="int">
+</parameter>
+</method>
+<method name="setRepeatMode"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="value" type="int">
+</parameter>
+</method>
+<method name="setStartDelay"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="startDelay" type="long">
+</parameter>
+</method>
+<method name="setValues"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="values" type="android.animation.PropertyValuesHolder...">
+</parameter>
+</method>
+<method name="setValues"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="values" type="T...">
+</parameter>
+</method>
+<field name="INFINITE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="-1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="RESTART"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="REVERSE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<interface name="ValueAnimator.AnimatorUpdateListener"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="onAnimationUpdate"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="animation" type="android.animation.ValueAnimator">
+</parameter>
+</method>
+</interface>
 </package>
 <package name="android.app"
 >
@@ -21707,6 +21674,21 @@
 <parameter name="tab" type="android.app.ActionBar.Tab">
 </parameter>
 </method>
+<method name="addTab"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="tab" type="android.app.ActionBar.Tab">
+</parameter>
+<parameter name="position" type="int">
+</parameter>
+</method>
 <method name="getCustomNavigationView"
  return="android.view.View"
  abstract="true"
@@ -21762,6 +21744,17 @@
  visibility="public"
 >
 </method>
+<method name="getSelectedTab"
+ return="android.app.ActionBar.Tab"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getSubtitle"
  return="java.lang.CharSequence"
  abstract="true"
@@ -21795,21 +21788,6 @@
  visibility="public"
 >
 </method>
-<method name="insertTab"
- return="void"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="tab" type="android.app.ActionBar.Tab">
-</parameter>
-<parameter name="position" type="int">
-</parameter>
-</method>
 <method name="isShowing"
  return="boolean"
  abstract="true"
@@ -21980,62 +21958,6 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="title" type="java.lang.CharSequence">
-</parameter>
-<parameter name="subtitle" type="java.lang.CharSequence">
-</parameter>
-</method>
-<method name="setStandardNavigationMode"
- return="void"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="titleResId" type="int">
-</parameter>
-<parameter name="subtitleResId" type="int">
-</parameter>
-</method>
-<method name="setStandardNavigationMode"
- return="void"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="title" type="java.lang.CharSequence">
-</parameter>
-</method>
-<method name="setStandardNavigationMode"
- return="void"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="titleResId" type="int">
-</parameter>
-</method>
-<method name="setStandardNavigationMode"
- return="void"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
 </method>
 <method name="setSubtitle"
  return="void"
@@ -22074,19 +21996,6 @@
  visibility="public"
 >
 </method>
-<method name="setTabNavigationMode"
- return="void"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="containerViewId" type="int">
-</parameter>
-</method>
 <method name="setTitle"
  return="void"
  abstract="true"
@@ -22230,8 +22139,8 @@
  visibility="public"
 >
 </constructor>
-<method name="getFragment"
- return="android.app.Fragment"
+<method name="getCustomView"
+ return="android.view.View"
  abstract="true"
  native="false"
  synchronized="false"
@@ -22263,6 +22172,17 @@
  visibility="public"
 >
 </method>
+<method name="getTag"
+ return="java.lang.Object"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getText"
  return="java.lang.CharSequence"
  abstract="true"
@@ -22285,7 +22205,7 @@
  visibility="public"
 >
 </method>
-<method name="setFragment"
+<method name="setCustomView"
  return="void"
  abstract="true"
  native="false"
@@ -22295,7 +22215,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="fragment" type="android.app.Fragment">
+<parameter name="view" type="android.view.View">
 </parameter>
 </method>
 <method name="setIcon"
@@ -22311,6 +22231,32 @@
 <parameter name="icon" type="android.graphics.drawable.Drawable">
 </parameter>
 </method>
+<method name="setTabListener"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="listener" type="android.app.ActionBar.TabListener">
+</parameter>
+</method>
+<method name="setTag"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="obj" type="java.lang.Object">
+</parameter>
+</method>
 <method name="setText"
  return="void"
  abstract="true"
@@ -22336,6 +22282,44 @@
 >
 </field>
 </class>
+<interface name="ActionBar.TabListener"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="onTabSelected"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="tab" type="android.app.ActionBar.Tab">
+</parameter>
+<parameter name="ft" type="android.app.FragmentTransaction">
+</parameter>
+</method>
+<method name="onTabUnselected"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="tab" type="android.app.ActionBar.Tab">
+</parameter>
+<parameter name="ft" type="android.app.FragmentTransaction">
+</parameter>
+</method>
+</interface>
 <class name="Activity"
  extends="android.view.ContextThemeWrapper"
  abstract="false"
@@ -28742,8 +28726,8 @@
 <parameter name="savedInstanceState" type="android.os.Bundle">
 </parameter>
 </method>
-<method name="onCreateAnimatable"
- return="android.animation.Animatable"
+<method name="onCreateAnimator"
+ return="android.animation.Animator"
  abstract="false"
  native="false"
  synchronized="false"
@@ -29326,6 +29310,17 @@
 <parameter name="fragment" type="android.app.Fragment">
 </parameter>
 </method>
+<method name="isEmpty"
+ return="boolean"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="remove"
  return="android.app.FragmentTransaction"
  abstract="true"
@@ -174313,6 +174308,29 @@
 <parameter name="flags" type="int">
 </parameter>
 </method>
+<method name="formatDateRange"
+ return="java.util.Formatter"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="formatter" type="java.util.Formatter">
+</parameter>
+<parameter name="startMillis" type="long">
+</parameter>
+<parameter name="endMillis" type="long">
+</parameter>
+<parameter name="flags" type="int">
+</parameter>
+<parameter name="timeZone" type="java.lang.String">
+</parameter>
+</method>
 <method name="formatDateTime"
  return="java.lang.String"
  abstract="false"
@@ -174806,7 +174824,7 @@
  value="8192"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -175921,16 +175939,6 @@
 <parameter name="cursorController" type="android.widget.TextView.CursorController">
 </parameter>
 </method>
-<field name="mCursorController"
- type="android.widget.TextView.CursorController"
- transient="false"
- volatile="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="protected"
->
-</field>
 </class>
 <class name="BaseKeyListener"
  extends="android.text.method.MetaKeyKeyListener"
@@ -191918,6 +191926,17 @@
  visibility="public"
 >
 </method>
+<method name="getFlags"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getHistoricalEventTime"
  return="long"
  abstract="false"
@@ -192555,6 +192574,8 @@
 </parameter>
 <parameter name="source" type="int">
 </parameter>
+<parameter name="flags" type="int">
+</parameter>
 </method>
 <method name="obtain"
  return="android.view.MotionEvent"
@@ -193011,6 +193032,17 @@
  visibility="public"
 >
 </field>
+<field name="FLAG_WINDOW_IS_OBSCURED"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 </class>
 <class name="MotionEvent.PointerCoords"
  extends="java.lang.Object"
@@ -195801,6 +195833,17 @@
  visibility="public"
 >
 </method>
+<method name="getFilterTouchesWhenObscured"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getFocusables"
  return="java.util.ArrayList&lt;android.view.View&gt;"
  abstract="false"
@@ -197232,6 +197275,19 @@
 <parameter name="canvas" type="android.graphics.Canvas">
 </parameter>
 </method>
+<method name="onFilterTouchEventForSecurity"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="event" type="android.view.MotionEvent">
+</parameter>
+</method>
 <method name="onFinishInflate"
  return="void"
  abstract="false"
@@ -198129,6 +198185,19 @@
 <parameter name="length" type="int">
 </parameter>
 </method>
+<method name="setFilterTouchesWhenObscured"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="enabled" type="boolean">
+</parameter>
+</method>
 <method name="setFocusable"
  return="void"
  abstract="false"
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index bfc73b5..f901bfb 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -28,7 +28,6 @@
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.ParcelFileDescriptor;
-// import android.os.RemoteException; // apparently not used
 import android.os.ServiceManager;
 import android.util.AndroidException;
 import android.view.IWindowManager;
@@ -142,11 +141,31 @@
                 String value = nextArgRequired();
                 intent.putExtra(key, Integer.valueOf(value));
                 hasIntentInfo = true;
+            } else if (opt.equals("--eia")) {
+                String key = nextArgRequired();
+                String value = nextArgRequired();
+                String[] strings = value.split(",");
+                int[] list = new int[strings.length];
+                for (int i = 0; i < strings.length; i++) {
+                    list[i] = Integer.valueOf(strings[i]);
+                }
+                intent.putExtra(key, list);
+                hasIntentInfo = true;
             } else if (opt.equals("--el")) {
                 String key = nextArgRequired();
                 String value = nextArgRequired();
                 intent.putExtra(key, Long.valueOf(value));
                 hasIntentInfo = true;
+            } else if (opt.equals("--ela")) {
+                String key = nextArgRequired();
+                String value = nextArgRequired();
+                String[] strings = value.split(",");
+                long[] list = new long[strings.length];
+                for (int i = 0; i < strings.length; i++) {
+                    list[i] = Long.valueOf(strings[i]);
+                }
+                intent.putExtra(key, list);
+                hasIntentInfo = true;
             } else if (opt.equals("--ez")) {
                 String key = nextArgRequired();
                 String value = nextArgRequired();
@@ -638,6 +657,8 @@
                 "        [--ez <EXTRA_KEY> <EXTRA_BOOLEAN_VALUE> ...]\n" +
                 "        [--ei <EXTRA_KEY> <EXTRA_INT_VALUE> ...]\n" +
                 "        [--el <EXTRA_KEY> <EXTRA_LONG_VALUE> ...]\n" +
+                "        [--eia <EXTRA_KEY> <EXTRA_INT_VALUE>[,<EXTRA_INT_VALUE...]]\n" +
+                "        [--ela <EXTRA_KEY> <EXTRA_LONG_VALUE>[,<EXTRA_LONG_VALUE...]]\n" +
                 "        [-n <COMPONENT>] [-f <FLAGS>]\n" +
                 "        [--grant-read-uri-permission] [--grant-write-uri-permission]\n" +
                 "        [--debug-log-resolution]\n" +
diff --git a/cmds/installd/commands.c b/cmds/installd/commands.c
index 2e87394..f6f80d1 100644
--- a/cmds/installd/commands.c
+++ b/cmds/installd/commands.c
@@ -136,7 +136,7 @@
 /* TODO(oam): depending on use case (ecryptfs or dmcrypt)
  * change implementation
  */
-static int disk_free()
+static int64_t disk_free()
 {
     struct statfs sfs;
     if (statfs(PKG_DIR_PREFIX, &sfs) == 0) {
@@ -154,18 +154,18 @@
  * also require that apps constantly modify file metadata even
  * when just reading from the cache, which is pretty awful.
  */
-int free_cache(int free_size)
+int free_cache(int64_t free_size)
 {
     const char *name;
     int dfd, subfd;
     DIR *d;
     struct dirent *de;
-    int avail;
+    int64_t avail;
 
     avail = disk_free();
     if (avail < 0) return -1;
 
-    LOGI("free_cache(%d) avail %d\n", free_size, avail);
+    LOGI("free_cache(%" PRId64 ") avail %" PRId64 "\n", free_size, avail);
     if (avail >= free_size) return 0;
 
     /* First try encrypted dir */
@@ -327,10 +327,10 @@
     return 0;
 }
 
-static int stat_size(struct stat *s)
+static int64_t stat_size(struct stat *s)
 {
-    int blksize = s->st_blksize;
-    int size = s->st_size;
+    int64_t blksize = s->st_blksize;
+    int64_t size = s->st_size;
 
     if (blksize) {
             /* round up to filesystem block size */
@@ -340,9 +340,9 @@
     return size;
 }
 
-static int calculate_dir_size(int dfd)
+static int64_t calculate_dir_size(int dfd)
 {
-    int size = 0;
+    int64_t size = 0;
     struct stat s;
     DIR *d;
     struct dirent *de;
@@ -378,7 +378,7 @@
 
 int get_size(const char *pkgname, const char *apkpath,
              const char *fwdlock_apkpath,
-             int *_codesize, int *_datasize, int *_cachesize, int encrypted_fs_flag)
+             int64_t *_codesize, int64_t *_datasize, int64_t *_cachesize, int encrypted_fs_flag)
 {
     DIR *d;
     int dfd;
@@ -386,9 +386,9 @@
     struct stat s;
     char path[PKG_PATH_MAX];
 
-    int codesize = 0;
-    int datasize = 0;
-    int cachesize = 0;
+    int64_t codesize = 0;
+    int64_t datasize = 0;
+    int64_t cachesize = 0;
 
         /* count the source apk as code -- but only if it's not
          * on the /system partition and its not on the sdcard.
@@ -445,7 +445,7 @@
             }
             subfd = openat(dfd, name, O_RDONLY | O_DIRECTORY);
             if (subfd >= 0) {
-                int size = calculate_dir_size(subfd);
+                int64_t size = calculate_dir_size(subfd);
                 if (!strcmp(name,"lib")) {
                     codesize += size;
                 } else if(!strcmp(name,"cache")) {
diff --git a/cmds/installd/installd.c b/cmds/installd/installd.c
index 882c493..c991845 100644
--- a/cmds/installd/installd.c
+++ b/cmds/installd/installd.c
@@ -60,7 +60,7 @@
 
 static int do_free_cache(char **arg, char reply[REPLY_MAX]) /* TODO int:free_size */
 {
-    return free_cache(atoi(arg[0])); /* free_size */
+    return free_cache((int64_t)atoll(arg[0])); /* free_size */
 }
 
 static int do_rm_cache(char **arg, char reply[REPLY_MAX])
@@ -75,15 +75,19 @@
 
 static int do_get_size(char **arg, char reply[REPLY_MAX])
 {
-    int codesize = 0;
-    int datasize = 0;
-    int cachesize = 0;
+    int64_t codesize = 0;
+    int64_t datasize = 0;
+    int64_t cachesize = 0;
     int res = 0;
 
         /* pkgdir, apkpath */
     res = get_size(arg[0], arg[1], arg[2], &codesize, &datasize, &cachesize, atoi(arg[3]));
 
-    sprintf(reply,"%d %d %d", codesize, datasize, cachesize);
+    /*
+     * Each int64_t can take up 22 characters printed out. Make sure it
+     * doesn't go over REPLY_MAX in the future.
+     */
+    snprintf(reply, REPLY_MAX, "%" PRId64 " %" PRId64 " %" PRId64, codesize, datasize, cachesize);
     return res;
 }
 
diff --git a/cmds/installd/installd.h b/cmds/installd/installd.h
index 8e4adb1..479e4b2 100644
--- a/cmds/installd/installd.h
+++ b/cmds/installd/installd.h
@@ -19,6 +19,8 @@
 
 #include <stdio.h>
 #include <stdlib.h>
+#include <stdint.h>
+#include <inttypes.h>
 #include <sys/stat.h>
 #include <dirent.h>
 #include <unistd.h>
@@ -105,7 +107,7 @@
 int rm_dex(const char *path);
 int protect(char *pkgname, gid_t gid);
 int get_size(const char *pkgname, const char *apkpath, const char *fwdlock_apkpath,
-             int *codesize, int *datasize, int *cachesize, int encrypted_fs_flag);
-int free_cache(int free_size);
+             int64_t *codesize, int64_t *datasize, int64_t *cachesize, int encrypted_fs_flag);
+int free_cache(int64_t free_size);
 int dexopt(const char *apk_path, uid_t uid, int is_public);
 int movefiles();
diff --git a/core/java/android/animation/Animatable.java b/core/java/android/animation/Animatable.java
deleted file mode 100644
index 3fdf200..0000000
--- a/core/java/android/animation/Animatable.java
+++ /dev/null
@@ -1,248 +0,0 @@
-/*
- * Copyright (C) 2010 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.animation;
-
-import android.view.animation.Interpolator;
-
-import java.util.ArrayList;
-
-/**
- * This is the superclass for classes which provide basic support for animations which can be
- * started, ended, and have <code>AnimatableListeners</code> added to them.
- */
-public abstract class Animatable implements Cloneable {
-
-
-    /**
-     * The set of listeners to be sent events through the life of an animation.
-     */
-    ArrayList<AnimatableListener> mListeners = null;
-
-    /**
-     * Starts this animation. If the animation has a nonzero startDelay, the animation will start
-     * running after that delay elapses. Note that the animation does not start synchronously with
-     * this call, because all animation events are posted to a central timing loop so that animation
-     * times are all synchronized on a single timing pulse on the UI thread. So the animation will
-     * start the next time that event handler processes events.
-     */
-    public void start() {
-    }
-
-    /**
-     * Cancels the animation. Unlike {@link #end()}, <code>cancel()</code> causes the animation to
-     * stop in its tracks, sending an {@link AnimatableListener#onAnimationCancel(Animatable)} to
-     * its listeners, followed by an {@link AnimatableListener#onAnimationEnd(Animatable)} message.
-     */
-    public void cancel() {
-    }
-
-    /**
-     * Ends the animation. This causes the animation to assign the end value of the property being
-     * animated, then calling the {@link AnimatableListener#onAnimationEnd(Animatable)} method on
-     * its listeners.
-     */
-    public void end() {
-    }
-
-    /**
-     * The amount of time, in milliseconds, to delay starting the animation after
-     * {@link #start()} is called.
-     *
-     * @return the number of milliseconds to delay running the animation
-     */
-    public abstract long getStartDelay();
-
-    /**
-     * The amount of time, in milliseconds, to delay starting the animation after
-     * {@link #start()} is called.
-
-     * @param startDelay The amount of the delay, in milliseconds
-     */
-    public abstract void setStartDelay(long startDelay);
-
-
-    /**
-     * Sets the length of the animation.
-     *
-     * @param duration The length of the animation, in milliseconds.
-     */
-    public abstract void setDuration(long duration);
-
-    /**
-     * Gets the length of the animation.
-     *
-     * @return The length of the animation, in milliseconds.
-     */
-    public abstract long getDuration();
-
-    /**
-     * The time interpolator used in calculating the elapsed fraction of this animation. The
-     * interpolator determines whether the animation runs with linear or non-linear motion,
-     * such as acceleration and deceleration. The default value is
-     * {@link android.view.animation.AccelerateDecelerateInterpolator}
-     *
-     * @param value the interpolator to be used by this animation
-     */
-    public abstract void setInterpolator(Interpolator value);
-
-    /**
-     * Returns whether this Animatable is currently running (having been started and not yet ended).
-     * @return Whether the Animatable is running.
-     */
-    public abstract boolean isRunning();
-
-    /**
-     * Adds a listener to the set of listeners that are sent events through the life of an
-     * animation, such as start, repeat, and end.
-     *
-     * @param listener the listener to be added to the current set of listeners for this animation.
-     */
-    public void addListener(AnimatableListener listener) {
-        if (mListeners == null) {
-            mListeners = new ArrayList<AnimatableListener>();
-        }
-        mListeners.add(listener);
-    }
-
-    /**
-     * Removes a listener from the set listening to this animation.
-     *
-     * @param listener the listener to be removed from the current set of listeners for this
-     *                 animation.
-     */
-    public void removeListener(AnimatableListener listener) {
-        if (mListeners == null) {
-            return;
-        }
-        mListeners.remove(listener);
-        if (mListeners.size() == 0) {
-            mListeners = null;
-        }
-    }
-
-    /**
-     * Gets the set of {@link AnimatableListener} objects that are currently
-     * listening for events on this <code>Animatable</code> object.
-     *
-     * @return ArrayList<AnimatableListener> The set of listeners.
-     */
-    public ArrayList<AnimatableListener> getListeners() {
-        return mListeners;
-    }
-
-    /**
-     * Removes all listeners from this object. This is equivalent to calling
-     * <code>getListeners()</code> followed by calling <code>clear()</code> on the
-     * returned list of listeners.
-     */
-    public void removeAllListeners() {
-        if (mListeners != null) {
-            mListeners.clear();
-            mListeners = null;
-        }
-    }
-
-    @Override
-    public Animatable clone() {
-        try {
-            final Animatable anim = (Animatable) super.clone();
-            if (mListeners != null) {
-                ArrayList<AnimatableListener> oldListeners = mListeners;
-                anim.mListeners = new ArrayList<AnimatableListener>();
-                int numListeners = oldListeners.size();
-                for (int i = 0; i < numListeners; ++i) {
-                    anim.mListeners.add(oldListeners.get(i));
-                }
-            }
-            return anim;
-        } catch (CloneNotSupportedException e) {
-           throw new AssertionError();
-        }
-    }
-
-    /**
-     * This method tells the object to use appropriate information to extract
-     * starting values for the animation. For example, a Sequencer object will pass
-     * this call to its child objects to tell them to set up the values. A
-     * PropertyAnimator object will use the information it has about its target object
-     * and PropertyValuesHolder objects to get the start values for its properties.
-     * An Animator object will ignore the request since it does not have enough
-     * information (such as a target object) to gather these values.
-     */
-    public void setupStartValues() {
-    }
-
-    /**
-     * This method tells the object to use appropriate information to extract
-     * ending values for the animation. For example, a Sequencer object will pass
-     * this call to its child objects to tell them to set up the values. A
-     * PropertyAnimator object will use the information it has about its target object
-     * and PropertyValuesHolder objects to get the start values for its properties.
-     * An Animator object will ignore the request since it does not have enough
-     * information (such as a target object) to gather these values.
-     */
-    public void setupEndValues() {
-    }
-
-    /**
-     * Sets the target object whose property will be animated by this animation. Not all subclasses
-     * operate on target objects (for example, {@link android.animation.Animator}, but this method
-     * is on the superclass for the convenience of dealing generically with those subclasses
-     * that do handle targets.
-     *
-     * @param target The object being animated
-     */
-    public void setTarget(Object target) {
-    }
-
-    /**
-     * <p>An animation listener receives notifications from an animation.
-     * Notifications indicate animation related events, such as the end or the
-     * repetition of the animation.</p>
-     */
-    public static interface AnimatableListener {
-        /**
-         * <p>Notifies the start of the animation.</p>
-         *
-         * @param animation The started animation.
-         */
-        void onAnimationStart(Animatable animation);
-
-        /**
-         * <p>Notifies the end of the animation. This callback is not invoked
-         * for animations with repeat count set to INFINITE.</p>
-         *
-         * @param animation The animation which reached its end.
-         */
-        void onAnimationEnd(Animatable animation);
-
-        /**
-         * <p>Notifies the cancellation of the animation. This callback is not invoked
-         * for animations with repeat count set to INFINITE.</p>
-         *
-         * @param animation The animation which was canceled.
-         */
-        void onAnimationCancel(Animatable animation);
-
-        /**
-         * <p>Notifies the repetition of the animation.</p>
-         *
-         * @param animation The animation which was repeated.
-         */
-        void onAnimationRepeat(Animatable animation);
-    }
-}
diff --git a/core/java/android/animation/Animator.java b/core/java/android/animation/Animator.java
old mode 100755
new mode 100644
index 8e947ec..2ada6d6
--- a/core/java/android/animation/Animator.java
+++ b/core/java/android/animation/Animator.java
@@ -16,461 +16,46 @@
 
 package android.animation;
 
-import android.content.Context;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
-import android.view.animation.AccelerateDecelerateInterpolator;
-import android.view.animation.AnimationUtils;
 import android.view.animation.Interpolator;
 
 import java.util.ArrayList;
-import java.util.HashMap;
 
 /**
- * This class provides a simple timing engine for running animations
- * which calculate animated values and set them on target objects.
- *
- * <p>There is a single timing pulse that all animations use. It runs in a
- * custom handler to ensure that property changes happen on the UI thread.</p>
- *
- * <p>By default, Animator uses non-linear time interpolation, via the
- * {@link AccelerateDecelerateInterpolator} class, which accelerates into and decelerates
- * out of an animation. This behavior can be changed by calling
- * {@link Animator#setInterpolator(Interpolator)}.</p>
+ * This is the superclass for classes which provide basic support for animations which can be
+ * started, ended, and have <code>AnimatorListeners</code> added to them.
  */
-public class Animator<T> extends Animatable {
+public abstract class Animator implements Cloneable {
 
-    /**
-     * Internal constants
-     */
-
-    /*
-     * The default amount of time in ms between animation frames
-     */
-    private static final long DEFAULT_FRAME_DELAY = 30;
-
-    /**
-     * Messages sent to timing handler: START is sent when an animation first begins, FRAME is sent
-     * by the handler to itself to process the next animation frame
-     */
-    private static final int ANIMATION_START = 0;
-    private static final int ANIMATION_FRAME = 1;
-
-    /**
-     * Values used with internal variable mPlayingState to indicate the current state of an
-     * animation.
-     */
-    private static final int STOPPED    = 0; // Not yet playing
-    private static final int RUNNING    = 1; // Playing normally
-    private static final int CANCELED   = 2; // cancel() called - need to end it
-    private static final int ENDED      = 3; // end() called - need to end it
-    private static final int SEEKED     = 4; // Seeked to some time value
-
-    /**
-     * Internal variables
-     * NOTE: This object implements the clone() method, making a deep copy of any referenced
-     * objects. As other non-trivial fields are added to this class, make sure to add logic
-     * to clone() to make deep copies of them.
-     */
-
-    // The first time that the animation's animateFrame() method is called. This time is used to
-    // determine elapsed time (and therefore the elapsed fraction) in subsequent calls
-    // to animateFrame()
-    private long mStartTime;
-
-    /**
-     * Set when setCurrentPlayTime() is called. If negative, animation is not currently seeked
-     * to a value.
-     */
-    private long mSeekTime = -1;
-
-    // The static sAnimationHandler processes the internal timing loop on which all animations
-    // are based
-    private static AnimationHandler sAnimationHandler;
-
-    // The static list of all active animations
-    private static final ArrayList<Animator> sAnimations = new ArrayList<Animator>();
-
-    // The set of animations to be started on the next animation frame
-    private static final ArrayList<Animator> sPendingAnimations = new ArrayList<Animator>();
-
-    // The time interpolator to be used if none is set on the animation
-    private static final Interpolator sDefaultInterpolator = new AccelerateDecelerateInterpolator();
-
-    // type evaluators for the three primitive types handled by this implementation
-    private static final TypeEvaluator sIntEvaluator = new IntEvaluator();
-    private static final TypeEvaluator sFloatEvaluator = new FloatEvaluator();
-    private static final TypeEvaluator sDoubleEvaluator = new DoubleEvaluator();
-
-    /**
-     * Used to indicate whether the animation is currently playing in reverse. This causes the
-     * elapsed fraction to be inverted to calculate the appropriate values.
-     */
-    private boolean mPlayingBackwards = false;
-
-    /**
-     * This variable tracks the current iteration that is playing. When mCurrentIteration exceeds the
-     * repeatCount (if repeatCount!=INFINITE), the animation ends
-     */
-    private int mCurrentIteration = 0;
-
-    /**
-     * Tracks whether a startDelay'd animation has begun playing through the startDelay.
-     */
-    private boolean mStartedDelay = false;
-
-    /**
-     * Tracks the time at which the animation began playing through its startDelay. This is
-     * different from the mStartTime variable, which is used to track when the animation became
-     * active (which is when the startDelay expired and the animation was added to the active
-     * animations list).
-     */
-    private long mDelayStartTime;
-
-    /**
-     * Flag that represents the current state of the animation. Used to figure out when to start
-     * an animation (if state == STOPPED). Also used to end an animation that
-     * has been cancel()'d or end()'d since the last animation frame. Possible values are
-     * STOPPED, RUNNING, ENDED, CANCELED.
-     */
-    private int mPlayingState = STOPPED;
-
-    /**
-     * Internal collections used to avoid set collisions as animations start and end while being
-     * processed.
-     */
-    private static final ArrayList<Animator> sEndingAnims = new ArrayList<Animator>();
-    private static final ArrayList<Animator> sDelayedAnims = new ArrayList<Animator>();
-    private static final ArrayList<Animator> sReadyAnims = new ArrayList<Animator>();
-
-    /**
-     * Flag that denotes whether the animation is set up and ready to go. Used to
-     * set up animation that has not yet been started.
-     */
-    boolean mInitialized = false;
-
-    //
-    // Backing variables
-    //
-
-    // How long the animation should last in ms
-    private long mDuration;
-
-    // The amount of time in ms to delay starting the animation after start() is called
-    private long mStartDelay = 0;
-
-    // The number of milliseconds between animation frames
-    private static long sFrameDelay = DEFAULT_FRAME_DELAY;
-
-    // The number of times the animation will repeat. The default is 0, which means the animation
-    // will play only once
-    private int mRepeatCount = 0;
-
-    /**
-     * The type of repetition that will occur when repeatMode is nonzero. RESTART means the
-     * animation will start from the beginning on every new cycle. REVERSE means the animation
-     * will reverse directions on each iteration.
-     */
-    private int mRepeatMode = RESTART;
-
-    /**
-     * The time interpolator to be used. The elapsed fraction of the animation will be passed
-     * through this interpolator to calculate the interpolated fraction, which is then used to
-     * calculate the animated values.
-     */
-    private Interpolator mInterpolator = sDefaultInterpolator;
 
     /**
      * The set of listeners to be sent events through the life of an animation.
      */
-    private ArrayList<AnimatorUpdateListener> mUpdateListeners = null;
+    ArrayList<AnimatorListener> mListeners = null;
 
     /**
-     * The property/value sets being animated.
+     * Starts this animation. If the animation has a nonzero startDelay, the animation will start
+     * running after that delay elapses. Note that the animation does not start synchronously with
+     * this call, because all animation events are posted to a central timing loop so that animation
+     * times are all synchronized on a single timing pulse on the UI thread. So the animation will
+     * start the next time that event handler processes events.
      */
-    PropertyValuesHolder[] mValues;
-
-    /**
-     * A hashmap of the PropertyValuesHolder objects. This map is used to lookup animated values
-     * by property name during calls to getAnimatedValue(String).
-     */
-    HashMap<String, PropertyValuesHolder> mValuesMap;
-
-    /**
-     * Public constants
-     */
-
-    /**
-     * When the animation reaches the end and <code>repeatCount</code> is INFINITE
-     * or a positive value, the animation restarts from the beginning.
-     */
-    public static final int RESTART = 1;
-    /**
-     * When the animation reaches the end and <code>repeatCount</code> is INFINITE
-     * or a positive value, the animation reverses direction on every iteration.
-     */
-    public static final int REVERSE = 2;
-    /**
-     * This value used used with the {@link #setRepeatCount(int)} property to repeat
-     * the animation indefinitely.
-     */
-    public static final int INFINITE = -1;
-
-    /**
-     * Creates a new Animator object. This default constructor is primarily for
-     * use internally; the other constructors which take parameters are more generally
-     * useful.
-     */
-    public Animator() {
+    public void start() {
     }
 
     /**
-     * Constructs an Animator object with the specified duration and set of
-     * values. If the values are a set of PropertyValuesHolder objects, then these objects
-     * define the potentially multiple properties being animated and the values the properties are
-     * animated between. Otherwise, the values define a single set of values animated between.
-     *
-     * @param duration The length of the animation, in milliseconds.
-     * @param values The set of values to animate between. If these values are not
-     * PropertyValuesHolder objects, then there should be more than one value, since the values
-     * determine the interval to animate between.
+     * Cancels the animation. Unlike {@link #end()}, <code>cancel()</code> causes the animation to
+     * stop in its tracks, sending an {@link android.animation.Animator.AnimatorListener#onAnimationCancel(Animator)} to
+     * its listeners, followed by an {@link android.animation.Animator.AnimatorListener#onAnimationEnd(Animator)} message.
      */
-    public Animator(long duration, T...values) {
-        mDuration = duration;
-        if (values.length > 0) {
-            setValues(values);
-        }
+    public void cancel() {
     }
 
     /**
-     * Sets the values, per property, being animated between. This function is called internally
-     * by the constructors of Animator that take a list of values. But an Animator can
-     * be constructed without values and this method can be called to set the values manually
-     * instead.
-     *
-     * @param values The set of values, per property, being animated between.
+     * Ends the animation. This causes the animation to assign the end value of the property being
+     * animated, then calling the {@link android.animation.Animator.AnimatorListener#onAnimationEnd(Animator)} method on
+     * its listeners.
      */
-    public void setValues(PropertyValuesHolder... values) {
-        int numValues = values.length;
-        mValues = values;
-        mValuesMap = new HashMap<String, PropertyValuesHolder>(numValues);
-        for (int i = 0; i < numValues; ++i) {
-            PropertyValuesHolder valuesHolder = (PropertyValuesHolder) values[i];
-            mValuesMap.put(valuesHolder.getPropertyName(), valuesHolder);
-        }
-    }
-
-    /**
-     * Returns the values that this Animator animates between. These values are stored in
-     * PropertyValuesHolder objects, even if the Animator was created with a simple list
-     * of value objects instead.
-     *
-     * @return PropertyValuesHolder[] An array of PropertyValuesHolder objects which hold the
-     * values, per property, that define the animation.
-     */
-    public PropertyValuesHolder[] getValues() {
-        return mValues;
-    }
-
-    /**
-     * Sets the values to animate between for this animation. If <code>values</code> is
-     * a set of PropertyValuesHolder objects, these objects will become the set of properties
-     * animated and the values that those properties are animated between. Otherwise, this method
-     * will set only one set of values for the Animator. Also, if the values are not
-     * PropertyValuesHolder objects and if there are already multiple sets of
-     * values defined for this Animator via
-     * more than one PropertyValuesHolder objects, this method will set the values for
-     * the first of those objects.
-     *
-     * @param values The set of values to animate between.
-     */
-    public void setValues(T... values) {
-        if (mValues == null || mValues.length == 0) {
-            setValues(new PropertyValuesHolder[]{
-                    new PropertyValuesHolder("", (Object[])values)});
-        } else {
-            PropertyValuesHolder valuesHolder = mValues[0];
-            valuesHolder.setValues(values);
-        }
-    }
-
-    /**
-     * This function is called immediately before processing the first animation
-     * frame of an animation. If there is a nonzero <code>startDelay</code>, the
-     * function is called after that delay ends.
-     * It takes care of the final initialization steps for the
-     * animation.
-     *
-     *  <p>Overrides of this method should call the superclass method to ensure
-     *  that internal mechanisms for the animation are set up correctly.</p>
-     */
-    void initAnimation() {
-        if (!mInitialized) {
-            int numValues = mValues.length;
-            for (int i = 0; i < numValues; ++i) {
-                mValues[i].init();
-            }
-            mCurrentIteration = 0;
-            mInitialized = true;
-        }
-    }
-
-
-    /**
-     * Sets the length of the animation.
-     *
-     * @param duration The length of the animation, in milliseconds.
-     */
-    public void setDuration(long duration) {
-        mDuration = duration;
-    }
-
-    /**
-     * Gets the length of the animation.
-     *
-     * @return The length of the animation, in milliseconds.
-     */
-    public long getDuration() {
-        return mDuration;
-    }
-
-    /**
-     * Sets the position of the animation to the specified point in time. This time should
-     * be between 0 and the total duration of the animation, including any repetition. If
-     * the animation has not yet been started, then it will not advance forward after it is
-     * set to this time; it will simply set the time to this value and perform any appropriate
-     * actions based on that time. If the animation is already running, then setCurrentPlayTime()
-     * will set the current playing time to this value and continue playing from that point.
-     *
-     * @param playTime The time, in milliseconds, to which the animation is advanced or rewound.
-     */
-    public void setCurrentPlayTime(long playTime) {
-        initAnimation();
-        long currentTime = AnimationUtils.currentAnimationTimeMillis();
-        if (mPlayingState != RUNNING) {
-            mSeekTime = playTime;
-            mPlayingState = SEEKED;
-        }
-        mStartTime = currentTime - playTime;
-        animationFrame(currentTime);
-    }
-
-    /**
-     * Gets the current position of the animation in time, which is equal to the current
-     * time minus the time that the animation started. An animation that is not yet started will
-     * return a value of zero.
-     *
-     * @return The current position in time of the animation.
-     */
-    public long getCurrentPlayTime() {
-        if (!mInitialized || mPlayingState == STOPPED) {
-            return 0;
-        }
-        return AnimationUtils.currentAnimationTimeMillis() - mStartTime;
-    }
-
-    /**
-     * This custom, static handler handles the timing pulse that is shared by
-     * all active animations. This approach ensures that the setting of animation
-     * values will happen on the UI thread and that all animations will share
-     * the same times for calculating their values, which makes synchronizing
-     * animations possible.
-     *
-     */
-    private static class AnimationHandler extends Handler {
-        /**
-         * There are only two messages that we care about: ANIMATION_START and
-         * ANIMATION_FRAME. The START message is sent when an animation's start()
-         * method is called. It cannot start synchronously when start() is called
-         * because the call may be on the wrong thread, and it would also not be
-         * synchronized with other animations because it would not start on a common
-         * timing pulse. So each animation sends a START message to the handler, which
-         * causes the handler to place the animation on the active animations queue and
-         * start processing frames for that animation.
-         * The FRAME message is the one that is sent over and over while there are any
-         * active animations to process.
-         */
-        @Override
-        public void handleMessage(Message msg) {
-            boolean callAgain = true;
-            switch (msg.what) {
-                // TODO: should we avoid sending frame message when starting if we
-                // were already running?
-                case ANIMATION_START:
-                    if (sAnimations.size() > 0 || sDelayedAnims.size() > 0) {
-                        callAgain = false;
-                    }
-                    // pendingAnims holds any animations that have requested to be started
-                    // We're going to clear sPendingAnimations, but starting animation may
-                    // cause more to be added to the pending list (for example, if one animation
-                    // starting triggers another starting). So we loop until sPendingAnimations
-                    // is empty.
-                    while (sPendingAnimations.size() > 0) {
-                        ArrayList<Animator> pendingCopy =
-                                (ArrayList<Animator>) sPendingAnimations.clone();
-                        sPendingAnimations.clear();
-                        int count = pendingCopy.size();
-                        for (int i = 0; i < count; ++i) {
-                            Animator anim = pendingCopy.get(i);
-                            // If the animation has a startDelay, place it on the delayed list
-                            if (anim.mStartDelay == 0 || anim.mPlayingState == ENDED ||
-                                    anim.mPlayingState == CANCELED) {
-                                anim.startAnimation();
-                            } else {
-                                sDelayedAnims.add(anim);
-                            }
-                        }
-                    }
-                    // fall through to process first frame of new animations
-                case ANIMATION_FRAME:
-                    // currentTime holds the common time for all animations processed
-                    // during this frame
-                    long currentTime = AnimationUtils.currentAnimationTimeMillis();
-
-                    // First, process animations currently sitting on the delayed queue, adding
-                    // them to the active animations if they are ready
-                    int numDelayedAnims = sDelayedAnims.size();
-                    for (int i = 0; i < numDelayedAnims; ++i) {
-                        Animator anim = sDelayedAnims.get(i);
-                        if (anim.delayedAnimationFrame(currentTime)) {
-                            sReadyAnims.add(anim);
-                        }
-                    }
-                    int numReadyAnims = sReadyAnims.size();
-                    if (numReadyAnims > 0) {
-                        for (int i = 0; i < numReadyAnims; ++i) {
-                            Animator anim = sReadyAnims.get(i);
-                            anim.startAnimation();
-                            sDelayedAnims.remove(anim);
-                        }
-                        sReadyAnims.clear();
-                    }
-
-                    // Now process all active animations. The return value from animationFrame()
-                    // tells the handler whether it should now be ended
-                    int numAnims = sAnimations.size();
-                    for (int i = 0; i < numAnims; ++i) {
-                        Animator anim = sAnimations.get(i);
-                        if (anim.animationFrame(currentTime)) {
-                            sEndingAnims.add(anim);
-                        }
-                    }
-                    if (sEndingAnims.size() > 0) {
-                        for (int i = 0; i < sEndingAnims.size(); ++i) {
-                            sEndingAnims.get(i).endAnimation();
-                        }
-                        sEndingAnims.clear();
-                    }
-
-                    // If there are still active or delayed animations, call the handler again
-                    // after the frameDelay
-                    if (callAgain && (!sAnimations.isEmpty() || !sDelayedAnims.isEmpty())) {
-                        sendEmptyMessageDelayed(ANIMATION_FRAME, sFrameDelay);
-                    }
-                    break;
-            }
-        }
+    public void end() {
     }
 
     /**
@@ -479,9 +64,7 @@
      *
      * @return the number of milliseconds to delay running the animation
      */
-    public long getStartDelay() {
-        return mStartDelay;
-    }
+    public abstract long getStartDelay();
 
     /**
      * The amount of time, in milliseconds, to delay starting the animation after
@@ -489,147 +72,22 @@
 
      * @param startDelay The amount of the delay, in milliseconds
      */
-    public void setStartDelay(long startDelay) {
-        this.mStartDelay = startDelay;
-    }
+    public abstract void setStartDelay(long startDelay);
+
 
     /**
-     * The amount of time, in milliseconds, between each frame of the animation. This is a
-     * requested time that the animation will attempt to honor, but the actual delay between
-     * frames may be different, depending on system load and capabilities. This is a static
-     * function because the same delay will be applied to all animations, since they are all
-     * run off of a single timing loop.
+     * Sets the length of the animation.
      *
-     * @return the requested time between frames, in milliseconds
+     * @param duration The length of the animation, in milliseconds.
      */
-    public static long getFrameDelay() {
-        return sFrameDelay;
-    }
+    public abstract void setDuration(long duration);
 
     /**
-     * The amount of time, in milliseconds, between each frame of the animation. This is a
-     * requested time that the animation will attempt to honor, but the actual delay between
-     * frames may be different, depending on system load and capabilities. This is a static
-     * function because the same delay will be applied to all animations, since they are all
-     * run off of a single timing loop.
+     * Gets the length of the animation.
      *
-     * @param frameDelay the requested time between frames, in milliseconds
+     * @return The length of the animation, in milliseconds.
      */
-    public static void setFrameDelay(long frameDelay) {
-        sFrameDelay = frameDelay;
-    }
-
-    /**
-     * The most recent value calculated by this <code>Animator</code> when there is just one
-     * property being animated. This value is only sensible while the animation is running. The main
-     * purpose for this read-only property is to retrieve the value from the <code>Animator</code>
-     * during a call to {@link AnimatorUpdateListener#onAnimationUpdate(Animator)}, which
-     * is called during each animation frame, immediately after the value is calculated.
-     *
-     * @return animatedValue The value most recently calculated by this <code>Animator</code> for
-     * the single property being animated. If there are several properties being animated
-     * (specified by several PropertyValuesHolder objects in the constructor), this function
-     * returns the animated value for the first of those objects.
-     */
-    public Object getAnimatedValue() {
-        if (mValues != null && mValues.length > 0) {
-            return mValues[0].getAnimatedValue();
-        }
-        // Shouldn't get here; should always have values unless Animator was set up wrong
-        return null;
-    }
-
-    /**
-     * The most recent value calculated by this <code>Animator</code> for <code>propertyName</code>.
-     * The main purpose for this read-only property is to retrieve the value from the
-     * <code>Animator</code> during a call to
-     * {@link AnimatorUpdateListener#onAnimationUpdate(Animator)}, which
-     * is called during each animation frame, immediately after the value is calculated.
-     *
-     * @return animatedValue The value most recently calculated for the named property
-     * by this <code>Animator</code>.
-     */
-    public Object getAnimatedValue(String propertyName) {
-        PropertyValuesHolder valuesHolder = mValuesMap.get(propertyName);
-        if (valuesHolder != null) {
-            return valuesHolder.getAnimatedValue();
-        } else {
-            // At least avoid crashing if called with bogus propertyName
-            return null;
-        }
-    }
-
-    /**
-     * Sets how many times the animation should be repeated. If the repeat
-     * count is 0, the animation is never repeated. If the repeat count is
-     * greater than 0 or {@link #INFINITE}, the repeat mode will be taken
-     * into account. The repeat count is 0 by default.
-     *
-     * @param value the number of times the animation should be repeated
-     */
-    public void setRepeatCount(int value) {
-        mRepeatCount = value;
-    }
-    /**
-     * Defines how many times the animation should repeat. The default value
-     * is 0.
-     *
-     * @return the number of times the animation should repeat, or {@link #INFINITE}
-     */
-    public int getRepeatCount() {
-        return mRepeatCount;
-    }
-
-    /**
-     * Defines what this animation should do when it reaches the end. This
-     * setting is applied only when the repeat count is either greater than
-     * 0 or {@link #INFINITE}. Defaults to {@link #RESTART}.
-     *
-     * @param value {@link #RESTART} or {@link #REVERSE}
-     */
-    public void setRepeatMode(int value) {
-        mRepeatMode = value;
-    }
-
-    /**
-     * Defines what this animation should do when it reaches the end.
-     *
-     * @return either one of {@link #REVERSE} or {@link #RESTART}
-     */
-    public int getRepeatMode() {
-        return mRepeatMode;
-    }
-
-    /**
-     * Adds a listener to the set of listeners that are sent update events through the life of
-     * an animation. This method is called on all listeners for every frame of the animation,
-     * after the values for the animation have been calculated.
-     *
-     * @param listener the listener to be added to the current set of listeners for this animation.
-     */
-    public void addUpdateListener(AnimatorUpdateListener listener) {
-        if (mUpdateListeners == null) {
-            mUpdateListeners = new ArrayList<AnimatorUpdateListener>();
-        }
-        mUpdateListeners.add(listener);
-    }
-
-    /**
-     * Removes a listener from the set listening to frame updates for this animation.
-     *
-     * @param listener the listener to be removed from the current set of update listeners
-     * for this animation.
-     */
-    public void removeUpdateListener(AnimatorUpdateListener listener) {
-        if (mUpdateListeners == null) {
-            return;
-        }
-        mUpdateListeners.remove(listener);
-        if (mUpdateListeners.size() == 0) {
-            mUpdateListeners = null;
-        }
-    }
-
+    public abstract long getDuration();
 
     /**
      * The time interpolator used in calculating the elapsed fraction of this animation. The
@@ -639,335 +97,152 @@
      *
      * @param value the interpolator to be used by this animation
      */
-    @Override
-    public void setInterpolator(Interpolator value) {
-        if (value != null) {
-            mInterpolator = value;
+    public abstract void setInterpolator(Interpolator value);
+
+    /**
+     * Returns whether this Animator is currently running (having been started and not yet ended).
+     * @return Whether the Animator is running.
+     */
+    public abstract boolean isRunning();
+
+    /**
+     * Adds a listener to the set of listeners that are sent events through the life of an
+     * animation, such as start, repeat, and end.
+     *
+     * @param listener the listener to be added to the current set of listeners for this animation.
+     */
+    public void addListener(AnimatorListener listener) {
+        if (mListeners == null) {
+            mListeners = new ArrayList<AnimatorListener>();
+        }
+        mListeners.add(listener);
+    }
+
+    /**
+     * Removes a listener from the set listening to this animation.
+     *
+     * @param listener the listener to be removed from the current set of listeners for this
+     *                 animation.
+     */
+    public void removeListener(AnimatorListener listener) {
+        if (mListeners == null) {
+            return;
+        }
+        mListeners.remove(listener);
+        if (mListeners.size() == 0) {
+            mListeners = null;
         }
     }
 
     /**
-     * Returns the timing interpolator that this Animator uses.
+     * Gets the set of {@link android.animation.Animator.AnimatorListener} objects that are currently
+     * listening for events on this <code>Animator</code> object.
      *
-     * @return The timing interpolator for this Animator.
+     * @return ArrayList<AnimatorListener> The set of listeners.
      */
-    public Interpolator getInterpolator() {
-        return mInterpolator;
+    public ArrayList<AnimatorListener> getListeners() {
+        return mListeners;
     }
 
     /**
-     * The type evaluator to be used when calculating the animated values of this animation.
-     * The system will automatically assign a float, int, or double evaluator based on the type
-     * of <code>startValue</code> and <code>endValue</code> in the constructor. But if these values
-     * are not one of these primitive types, or if different evaluation is desired (such as is
-     * necessary with int values that represent colors), a custom evaluator needs to be assigned.
-     * For example, when running an animation on color values, the {@link RGBEvaluator}
-     * should be used to get correct RGB color interpolation.
-     *
-     * <p>If this Animator has only one set of values being animated between, this evaluator
-     * will be used for that set. If there are several sets of values being animated, which is
-     * the case if PropertyValuesHOlder objects were set on the Animator, then the evaluator
-     * is assigned just to the first PropertyValuesHolder object.</p>
-     *
-     * @param value the evaluator to be used this animation
+     * Removes all listeners from this object. This is equivalent to calling
+     * <code>getListeners()</code> followed by calling <code>clear()</code> on the
+     * returned list of listeners.
      */
-    public void setEvaluator(TypeEvaluator value) {
-        if (value != null && mValues != null && mValues.length > 0) {
-            mValues[0].setEvaluator(value);
-        }
-    }
-
-    /**
-     * Start the animation playing. This version of start() takes a boolean flag that indicates
-     * whether the animation should play in reverse. The flag is usually false, but may be set
-     * to true if called from the reverse() method/
-     *
-     * @param playBackwards Whether the Animator should start playing in reverse.
-     */
-    private void start(boolean playBackwards) {
-        mPlayingBackwards = playBackwards;
-        if ((mStartDelay == 0) && (Thread.currentThread() == Looper.getMainLooper().getThread())) {
-            // This sets the initial value of the animation, prior to actually starting it running
-            setCurrentPlayTime(getCurrentPlayTime());
-        }
-        mPlayingState = STOPPED;
-        mStartedDelay = false;
-        sPendingAnimations.add(this);
-        if (sAnimationHandler == null) {
-            sAnimationHandler = new AnimationHandler();
-        }
-        // TODO: does this put too many messages on the queue if the handler
-        // is already running?
-        sAnimationHandler.sendEmptyMessage(ANIMATION_START);
-    }
-
-    @Override
-    public void start() {
-        start(false);
-    }
-
-    @Override
-    public void cancel() {
+    public void removeAllListeners() {
         if (mListeners != null) {
-            ArrayList<AnimatableListener> tmpListeners =
-                    (ArrayList<AnimatableListener>) mListeners.clone();
-            for (AnimatableListener listener : tmpListeners) {
-                listener.onAnimationCancel(this);
-            }
-        }
-        // Just set the CANCELED flag - this causes the animation to end the next time a frame
-        // is processed.
-        mPlayingState = CANCELED;
-    }
-
-    @Override
-    public void end() {
-        if (!sAnimations.contains(this) && !sPendingAnimations.contains(this)) {
-            // Special case if the animation has not yet started; get it ready for ending
-            mStartedDelay = false;
-            sPendingAnimations.add(this);
-            if (sAnimationHandler == null) {
-                sAnimationHandler = new AnimationHandler();
-            }
-            sAnimationHandler.sendEmptyMessage(ANIMATION_START);
-        }
-        // Just set the ENDED flag - this causes the animation to end the next time a frame
-        // is processed.
-        mPlayingState = ENDED;
-    }
-
-    @Override
-    public boolean isRunning() {
-        // ENDED or CANCELED indicate that it has been ended or canceled, but not processed yet
-        return (mPlayingState == RUNNING || mPlayingState == ENDED || mPlayingState == CANCELED);
-    }
-
-    /**
-     * Plays the Animator in reverse. If the animation is already running,
-     * it will stop itself and play backwards from the point reached when reverse was called.
-     * If the animation is not currently running, then it will start from the end and
-     * play backwards. This behavior is only set for the current animation; future playing
-     * of the animation will use the default behavior of playing forward.
-     */
-    public void reverse() {
-        mPlayingBackwards = !mPlayingBackwards;
-        if (mPlayingState == RUNNING) {
-            long currentTime = AnimationUtils.currentAnimationTimeMillis();
-            long currentPlayTime = currentTime - mStartTime;
-            long timeLeft = mDuration - currentPlayTime;
-            mStartTime = currentTime - timeLeft;
-        } else {
-            start(true);
-        }
-    }
-
-    /**
-     * Called internally to end an animation by removing it from the animations list. Must be
-     * called on the UI thread.
-     */
-    private void endAnimation() {
-        sAnimations.remove(this);
-        mPlayingState = STOPPED;
-        if (mListeners != null) {
-            ArrayList<AnimatableListener> tmpListeners =
-                    (ArrayList<AnimatableListener>) mListeners.clone();
-            for (AnimatableListener listener : tmpListeners) {
-                listener.onAnimationEnd(this);
-            }
-        }
-    }
-
-    /**
-     * Called internally to start an animation by adding it to the active animations list. Must be
-     * called on the UI thread.
-     */
-    private void startAnimation() {
-        initAnimation();
-        sAnimations.add(this);
-        if (mListeners != null) {
-            ArrayList<AnimatableListener> tmpListeners =
-                    (ArrayList<AnimatableListener>) mListeners.clone();
-            for (AnimatableListener listener : tmpListeners) {
-                listener.onAnimationStart(this);
-            }
-        }
-    }
-
-    /**
-     * Internal function called to process an animation frame on an animation that is currently
-     * sleeping through its <code>startDelay</code> phase. The return value indicates whether it
-     * should be woken up and put on the active animations queue.
-     *
-     * @param currentTime The current animation time, used to calculate whether the animation
-     * has exceeded its <code>startDelay</code> and should be started.
-     * @return True if the animation's <code>startDelay</code> has been exceeded and the animation
-     * should be added to the set of active animations.
-     */
-    private boolean delayedAnimationFrame(long currentTime) {
-        if (mPlayingState == CANCELED || mPlayingState == ENDED) {
-            // end the delay, process an animation frame to actually cancel it
-            return true;
-        }
-        if (!mStartedDelay) {
-            mStartedDelay = true;
-            mDelayStartTime = currentTime;
-        } else {
-            long deltaTime = currentTime - mDelayStartTime;
-            if (deltaTime > mStartDelay) {
-                // startDelay ended - start the anim and record the
-                // mStartTime appropriately
-                mStartTime = currentTime - (deltaTime - mStartDelay);
-                mPlayingState = RUNNING;
-                return true;
-            }
-        }
-        return false;
-    }
-
-    /**
-     * This internal function processes a single animation frame for a given animation. The
-     * currentTime parameter is the timing pulse sent by the handler, used to calculate the
-     * elapsed duration, and therefore
-     * the elapsed fraction, of the animation. The return value indicates whether the animation
-     * should be ended (which happens when the elapsed time of the animation exceeds the
-     * animation's duration, including the repeatCount).
-     *
-     * @param currentTime The current time, as tracked by the static timing handler
-     * @return true if the animation's duration, including any repetitions due to
-     * <code>repeatCount</code> has been exceeded and the animation should be ended.
-     */
-    private boolean animationFrame(long currentTime) {
-        boolean done = false;
-
-        if (mPlayingState == STOPPED) {
-            mPlayingState = RUNNING;
-            if (mSeekTime < 0) {
-                mStartTime = currentTime;
-            } else {
-                mStartTime = currentTime - mSeekTime;
-                // Now that we're playing, reset the seek time
-                mSeekTime = -1;
-            }
-        }
-        switch (mPlayingState) {
-        case RUNNING:
-        case SEEKED:
-            float fraction = (float)(currentTime - mStartTime) / mDuration;
-            if (fraction >= 1f) {
-                if (mCurrentIteration < mRepeatCount || mRepeatCount == INFINITE) {
-                    // Time to repeat
-                    if (mListeners != null) {
-                        for (AnimatableListener listener : mListeners) {
-                            listener.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;
-                    mStartTime += mDuration;
-                } else {
-                    done = true;
-                    fraction = Math.min(fraction, 1.0f);
-                }
-            }
-            if (mPlayingBackwards) {
-                fraction = 1f - fraction;
-            }
-            animateValue(fraction);
-            break;
-        case ENDED:
-            // The final value set on the target varies, depending on whether the animation
-            // was supposed to repeat an odd number of times
-            if (mRepeatCount > 0 && (mRepeatCount & 0x01) == 1) {
-                animateValue(0f);
-            } else {
-                animateValue(1f);
-            }
-            // Fall through to set done flag
-        case CANCELED:
-            done = true;
-            mPlayingState = STOPPED;
-            break;
-        }
-
-        return done;
-    }
-
-    /**
-     * This method is called with the elapsed fraction of the animation during every
-     * animation frame. This function turns the elapsed fraction into an interpolated fraction
-     * and then into an animated value (from the evaluator. The function is called mostly during
-     * animation updates, but it is also called when the <code>end()</code>
-     * function is called, to set the final value on the property.
-     *
-     * <p>Overrides of this method must call the superclass to perform the calculation
-     * of the animated value.</p>
-     *
-     * @param fraction The elapsed fraction of the animation.
-     */
-    void animateValue(float fraction) {
-        fraction = mInterpolator.getInterpolation(fraction);
-        int numValues = mValues.length;
-        for (int i = 0; i < numValues; ++i) {
-            mValues[i].calculateValue(fraction);
-        }
-        if (mUpdateListeners != null) {
-            int numListeners = mUpdateListeners.size();
-            for (int i = 0; i < numListeners; ++i) {
-                mUpdateListeners.get(i).onAnimationUpdate(this);
-            }
+            mListeners.clear();
+            mListeners = null;
         }
     }
 
     @Override
     public Animator clone() {
-        final Animator anim = (Animator) super.clone();
-        if (mUpdateListeners != null) {
-            ArrayList<AnimatorUpdateListener> oldListeners = mUpdateListeners;
-            anim.mUpdateListeners = new ArrayList<AnimatorUpdateListener>();
-            int numListeners = oldListeners.size();
-            for (int i = 0; i < numListeners; ++i) {
-                anim.mUpdateListeners.add(oldListeners.get(i));
+        try {
+            final Animator anim = (Animator) super.clone();
+            if (mListeners != null) {
+                ArrayList<AnimatorListener> oldListeners = mListeners;
+                anim.mListeners = new ArrayList<AnimatorListener>();
+                int numListeners = oldListeners.size();
+                for (int i = 0; i < numListeners; ++i) {
+                    anim.mListeners.add(oldListeners.get(i));
+                }
             }
+            return anim;
+        } catch (CloneNotSupportedException e) {
+           throw new AssertionError();
         }
-        anim.mSeekTime = -1;
-        anim.mPlayingBackwards = false;
-        anim.mCurrentIteration = 0;
-        anim.mInitialized = false;
-        anim.mPlayingState = STOPPED;
-        anim.mStartedDelay = false;
-        PropertyValuesHolder[] oldValues = mValues;
-        if (oldValues != null) {
-            int numValues = oldValues.length;
-            anim.mValues = new PropertyValuesHolder[numValues];
-            for (int i = 0; i < numValues; ++i) {
-                anim.mValues[i] = oldValues[i].clone();
-            }
-            anim.mValuesMap = new HashMap<String, PropertyValuesHolder>(numValues);
-            for (int i = 0; i < numValues; ++i) {
-                PropertyValuesHolder valuesHolder = mValues[i];
-                anim.mValuesMap.put(valuesHolder.getPropertyName(), valuesHolder);
-            }
-        }
-        return anim;
     }
 
     /**
-     * Implementors of this interface can add themselves as update listeners
-     * to an <code>Animator</code> instance to receive callbacks on every animation
-     * frame, after the current frame's values have been calculated for that
-     * <code>Animator</code>.
+     * This method tells the object to use appropriate information to extract
+     * starting values for the animation. For example, a AnimatorSet object will pass
+     * this call to its child objects to tell them to set up the values. A
+     * ObjectAnimator object will use the information it has about its target object
+     * and PropertyValuesHolder objects to get the start values for its properties.
+     * An ValueAnimator object will ignore the request since it does not have enough
+     * information (such as a target object) to gather these values.
      */
-    public static interface AnimatorUpdateListener {
+    public void setupStartValues() {
+    }
+
+    /**
+     * This method tells the object to use appropriate information to extract
+     * ending values for the animation. For example, a AnimatorSet object will pass
+     * this call to its child objects to tell them to set up the values. A
+     * ObjectAnimator object will use the information it has about its target object
+     * and PropertyValuesHolder objects to get the start values for its properties.
+     * An ValueAnimator object will ignore the request since it does not have enough
+     * information (such as a target object) to gather these values.
+     */
+    public void setupEndValues() {
+    }
+
+    /**
+     * Sets the target object whose property will be animated by this animation. Not all subclasses
+     * operate on target objects (for example, {@link ValueAnimator}, but this method
+     * is on the superclass for the convenience of dealing generically with those subclasses
+     * that do handle targets.
+     *
+     * @param target The object being animated
+     */
+    public void setTarget(Object target) {
+    }
+
+    /**
+     * <p>An animation listener receives notifications from an animation.
+     * Notifications indicate animation related events, such as the end or the
+     * repetition of the animation.</p>
+     */
+    public static interface AnimatorListener {
         /**
-         * <p>Notifies the occurrence of another frame of the animation.</p>
+         * <p>Notifies the start of the animation.</p>
+         *
+         * @param animation The started animation.
+         */
+        void onAnimationStart(Animator animation);
+
+        /**
+         * <p>Notifies the end of the animation. This callback is not invoked
+         * for animations with repeat count set to INFINITE.</p>
+         *
+         * @param animation The animation which reached its end.
+         */
+        void onAnimationEnd(Animator animation);
+
+        /**
+         * <p>Notifies the cancellation of the animation. This callback is not invoked
+         * for animations with repeat count set to INFINITE.</p>
+         *
+         * @param animation The animation which was canceled.
+         */
+        void onAnimationCancel(Animator animation);
+
+        /**
+         * <p>Notifies the repetition of the animation.</p>
          *
          * @param animation The animation which was repeated.
          */
-        void onAnimationUpdate(Animator animation);
-
+        void onAnimationRepeat(Animator animation);
     }
-}
\ No newline at end of file
+}
diff --git a/core/java/android/animation/AnimatableInflater.java b/core/java/android/animation/AnimatorInflater.java
similarity index 83%
rename from core/java/android/animation/AnimatableInflater.java
rename to core/java/android/animation/AnimatorInflater.java
index 88fa77e..0016459 100644
--- a/core/java/android/animation/AnimatableInflater.java
+++ b/core/java/android/animation/AnimatorInflater.java
@@ -30,7 +30,7 @@
 import java.util.ArrayList;
 
 /**
- * This class is used to instantiate menu XML files into Animatable objects.
+ * This class is used to instantiate menu XML files into Animator objects.
  * <p>
  * For performance reasons, menu inflation relies heavily on pre-processing of
  * XML files that is done at build time. Therefore, it is not currently possible
@@ -38,10 +38,10 @@
  * it only works with an XmlPullParser returned from a compiled resource (R.
  * <em>something</em> file.)
  */
-public class AnimatableInflater {
+public class AnimatorInflater {
 
     /**
-     * These flags are used when parsing Sequencer objects
+     * These flags are used when parsing AnimatorSet objects
      */
     private static final int TOGETHER = 0;
     private static final int SEQUENTIALLY = 1;
@@ -56,20 +56,20 @@
     private static final int VALUE_TYPE_CUSTOM      = 4;
 
     /**
-     * Loads an {@link Animatable} object from a resource
+     * Loads an {@link Animator} object from a resource
      *
      * @param context Application context used to access resources
      * @param id The resource id of the animation to load
-     * @return The animatable object reference by the specified id
+     * @return The animator object reference by the specified id
      * @throws android.content.res.Resources.NotFoundException when the animation cannot be loaded
      */
-    public static Animatable loadAnimatable(Context context, int id)
+    public static Animator loadAnimator(Context context, int id)
             throws NotFoundException {
 
         XmlResourceParser parser = null;
         try {
             parser = context.getResources().getAnimation(id);
-            return createAnimatableFromXml(context, parser);
+            return createAnimatorFromXml(context, parser);
         } catch (XmlPullParserException ex) {
             Resources.NotFoundException rnf =
                     new Resources.NotFoundException("Can't load animation resource ID #0x" +
@@ -87,18 +87,18 @@
         }
     }
 
-    private static Animatable createAnimatableFromXml(Context c, XmlPullParser parser)
+    private static Animator createAnimatorFromXml(Context c, XmlPullParser parser)
             throws XmlPullParserException, IOException {
 
-        return createAnimatableFromXml(c, parser, Xml.asAttributeSet(parser), null, 0);
+        return createAnimatorFromXml(c, parser, Xml.asAttributeSet(parser), null, 0);
     }
 
-    private static Animatable createAnimatableFromXml(Context c, XmlPullParser parser,
-            AttributeSet attrs, Sequencer parent, int sequenceOrdering)
+    private static Animator createAnimatorFromXml(Context c, XmlPullParser parser,
+            AttributeSet attrs, AnimatorSet parent, int sequenceOrdering)
             throws XmlPullParserException, IOException {
 
-        Animatable anim = null;
-        ArrayList<Animatable> childAnims = null;
+        Animator anim = null;
+        ArrayList<Animator> childAnims = null;
 
         // Make sure we are on a start tag.
         int type;
@@ -113,17 +113,17 @@
 
             String  name = parser.getName();
 
-            if (name.equals("property")) {
-                anim = loadPropertyAnimator(c, attrs);
+            if (name.equals("objectAnimator")) {
+                anim = loadObjectAnimator(c, attrs);
             } else if (name.equals("animator")) {
                 anim = loadAnimator(c, attrs, null);
-            } else if (name.equals("sequencer")) {
-                anim = new Sequencer();
+            } else if (name.equals("set")) {
+                anim = new AnimatorSet();
                 TypedArray a = c.obtainStyledAttributes(attrs,
-                        com.android.internal.R.styleable.Sequencer);
-                int ordering = a.getInt(com.android.internal.R.styleable.Sequencer_ordering,
+                        com.android.internal.R.styleable.AnimatorSet);
+                int ordering = a.getInt(com.android.internal.R.styleable.AnimatorSet_ordering,
                         TOGETHER);
-                createAnimatableFromXml(c, parser, attrs, (Sequencer) anim,  ordering);
+                createAnimatorFromXml(c, parser, attrs, (AnimatorSet) anim,  ordering);
                 a.recycle();
             } else {
                 throw new RuntimeException("Unknown animator name: " + parser.getName());
@@ -131,15 +131,15 @@
 
             if (parent != null) {
                 if (childAnims == null) {
-                    childAnims = new ArrayList<Animatable>();
+                    childAnims = new ArrayList<Animator>();
                 }
                 childAnims.add(anim);
             }
         }
         if (parent != null && childAnims != null) {
-            Animatable[] animsArray = new Animatable[childAnims.size()];
+            Animator[] animsArray = new Animator[childAnims.size()];
             int index = 0;
-            for (Animatable a : childAnims) {
+            for (Animator a : childAnims) {
                 animsArray[index++] = a;
             }
             if (sequenceOrdering == TOGETHER) {
@@ -153,10 +153,10 @@
 
     }
 
-    private static PropertyAnimator loadPropertyAnimator(Context context, AttributeSet attrs)
+    private static ObjectAnimator loadObjectAnimator(Context context, AttributeSet attrs)
             throws NotFoundException {
 
-        PropertyAnimator anim = new PropertyAnimator();
+        ObjectAnimator anim = new ObjectAnimator();
 
         loadAnimator(context, attrs, anim);
 
@@ -179,7 +179,7 @@
      * @param context the application environment
      * @param attrs the set of attributes holding the animation parameters
      */
-    private static Animator loadAnimator(Context context, AttributeSet attrs, Animator anim)
+    private static ValueAnimator loadAnimator(Context context, AttributeSet attrs, ValueAnimator anim)
             throws NotFoundException {
 
         TypedArray a =
@@ -236,7 +236,7 @@
         }
 
         if (anim == null) {
-            anim = new Animator(duration, valueFrom, valueTo);
+            anim = new ValueAnimator(duration, valueFrom, valueTo);
         } else {
             anim.setDuration(duration);
             anim.setValues(valueFrom, valueTo);
@@ -251,7 +251,7 @@
         if (a.hasValue(com.android.internal.R.styleable.Animator_repeatMode)) {
             anim.setRepeatMode(
                     a.getInt(com.android.internal.R.styleable.Animator_repeatMode,
-                            Animator.RESTART));
+                            ValueAnimator.RESTART));
         }
         if (evaluator != null) {
             anim.setEvaluator(evaluator);
diff --git a/core/java/android/animation/AnimatableListenerAdapter.java b/core/java/android/animation/AnimatorListenerAdapter.java
similarity index 73%
rename from core/java/android/animation/AnimatableListenerAdapter.java
rename to core/java/android/animation/AnimatorListenerAdapter.java
index c169b28..6182389 100644
--- a/core/java/android/animation/AnimatableListenerAdapter.java
+++ b/core/java/android/animation/AnimatorListenerAdapter.java
@@ -16,41 +16,39 @@
 
 package android.animation;
 
-import android.animation.Animatable.AnimatableListener;
-
 /**
- * This adapter class provides empty implementations of the methods from {@link AnimatableListener}.
+ * This adapter class provides empty implementations of the methods from {@link android.animation.Animator.AnimatorListener}.
  * Any custom listener that cares only about a subset of the methods of this listener can
  * simply subclass this adapter class instead of implementing the interface directly.
  */
-public abstract class AnimatableListenerAdapter implements AnimatableListener {
+public abstract class AnimatorListenerAdapter implements Animator.AnimatorListener {
 
     /**
      * {@inheritdoc}
      */
     @Override
-    public void onAnimationCancel(Animatable animation) {
+    public void onAnimationCancel(Animator animation) {
     }
 
     /**
      * {@inheritdoc}
      */
     @Override
-    public void onAnimationEnd(Animatable animation) {
+    public void onAnimationEnd(Animator animation) {
     }
 
     /**
      * {@inheritdoc}
      */
     @Override
-    public void onAnimationRepeat(Animatable animation) {
+    public void onAnimationRepeat(Animator animation) {
     }
 
     /**
      * {@inheritdoc}
      */
     @Override
-    public void onAnimationStart(Animatable animation) {
+    public void onAnimationStart(Animator animation) {
     }
 
 }
diff --git a/core/java/android/animation/Sequencer.java b/core/java/android/animation/AnimatorSet.java
similarity index 72%
rename from core/java/android/animation/Sequencer.java
rename to core/java/android/animation/AnimatorSet.java
index 04bede0..a8385e4 100644
--- a/core/java/android/animation/Sequencer.java
+++ b/core/java/android/animation/AnimatorSet.java
@@ -16,35 +16,31 @@
 
 package android.animation;
 
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.util.AttributeSet;
-import android.view.animation.AnimationUtils;
 import android.view.animation.Interpolator;
 
 import java.util.ArrayList;
 import java.util.HashMap;
 
 /**
- * This class plays a set of {@link Animatable} objects in the specified order. Animations
+ * This class plays a set of {@link Animator} objects in the specified order. Animations
  * can be set up to play together, in sequence, or after a specified delay.
  *
- * <p>There are two different approaches to adding animations to a <code>Sequencer</code>:
- * either the {@link Sequencer#playTogether(Animatable[]) playTogether()} or
- * {@link Sequencer#playSequentially(Animatable[]) playSequentially()} methods can be called to add
- * a set of animations all at once, or the {@link Sequencer#play(Animatable)} can be
- * used in conjunction with methods in the {@link android.animation.Sequencer.Builder Builder}
+ * <p>There are two different approaches to adding animations to a <code>AnimatorSet</code>:
+ * either the {@link AnimatorSet#playTogether(Animator[]) playTogether()} or
+ * {@link AnimatorSet#playSequentially(Animator[]) playSequentially()} methods can be called to add
+ * a set of animations all at once, or the {@link AnimatorSet#play(Animator)} can be
+ * used in conjunction with methods in the {@link AnimatorSet.Builder Builder}
  * class to add animations
  * one by one.</p>
  *
- * <p>It is possible to set up a <code>Sequencer</code> with circular dependencies between
+ * <p>It is possible to set up a <code>AnimatorSet</code> with circular dependencies between
  * its animations. For example, an animation a1 could be set up to start before animation a2, a2
  * before a3, and a3 before a1. The results of this configuration are undefined, but will typically
  * result in none of the affected animations being played. Because of this (and because
  * circular dependencies do not make logical sense anyway), circular dependencies
  * should be avoided, and the dependency flow of animations should only be in one direction.
  */
-public final class Sequencer extends Animatable {
+public final class AnimatorSet extends Animator {
 
     /**
      * Internal variables
@@ -55,21 +51,21 @@
 
     /**
      * Tracks animations currently being played, so that we know what to
-     * cancel or end when cancel() or end() is called on this Sequencer
+     * cancel or end when cancel() or end() is called on this AnimatorSet
      */
-    private ArrayList<Animatable> mPlayingSet = new ArrayList<Animatable>();
+    private ArrayList<Animator> mPlayingSet = new ArrayList<Animator>();
 
     /**
-     * Contains all nodes, mapped to their respective Animatables. When new
-     * dependency information is added for an Animatable, we want to add it
-     * to a single node representing that Animatable, not create a new Node
+     * Contains all nodes, mapped to their respective Animators. When new
+     * dependency information is added for an Animator, we want to add it
+     * to a single node representing that Animator, not create a new Node
      * if one already exists.
      */
-    private HashMap<Animatable, Node> mNodeMap = new HashMap<Animatable, Node>();
+    private HashMap<Animator, Node> mNodeMap = new HashMap<Animator, Node>();
 
     /**
-     * Set of all nodes created for this Sequencer. This list is used upon
-     * starting the sequencer, and the nodes are placed in sorted order into the
+     * Set of all nodes created for this AnimatorSet. This list is used upon
+     * starting the set, and the nodes are placed in sorted order into the
      * sortedNodes collection.
      */
     private ArrayList<Node> mNodes = new ArrayList<Node>();
@@ -88,12 +84,12 @@
      */
     private boolean mNeedsSort = true;
 
-    private SequencerAnimatableListener mSequenceListener = null;
+    private AnimatorSetListener mSetListener = null;
 
     /**
-     * Flag indicating that the Sequencer has been canceled (by calling cancel() or end()).
+     * Flag indicating that the AnimatorSet has been canceled (by calling cancel() or end()).
      * This flag is used to avoid starting other animations when currently-playing
-     * child animations of this Sequencer end.
+     * child animations of this AnimatorSet end.
      */
     boolean mCanceled = false;
 
@@ -102,55 +98,55 @@
 
 
     // How long the child animations should last in ms. The default value is negative, which
-    // simply means that there is no duration set on the Sequencer. When a real duration is
+    // simply means that there is no duration set on the AnimatorSet. When a real duration is
     // set, it is passed along to the child animations.
     private long mDuration = -1;
 
 
     /**
-     * Sets up this Sequencer to play all of the supplied animations at the same time.
+     * Sets up this AnimatorSet to play all of the supplied animations at the same time.
      *
-     * @param sequenceItems The animations that will be started simultaneously.
+     * @param items The animations that will be started simultaneously.
      */
-    public void playTogether(Animatable... sequenceItems) {
-        if (sequenceItems != null) {
+    public void playTogether(Animator... items) {
+        if (items != null) {
             mNeedsSort = true;
-            Builder builder = play(sequenceItems[0]);
-            for (int i = 1; i < sequenceItems.length; ++i) {
-                builder.with(sequenceItems[i]);
+            Builder builder = play(items[0]);
+            for (int i = 1; i < items.length; ++i) {
+                builder.with(items[i]);
             }
         }
     }
 
     /**
-     * Sets up this Sequencer to play each of the supplied animations when the
+     * Sets up this AnimatorSet to play each of the supplied animations when the
      * previous animation ends.
      *
-     * @param sequenceItems The aniamtions that will be started one after another.
+     * @param items The aniamtions that will be started one after another.
      */
-    public void playSequentially(Animatable... sequenceItems) {
-        if (sequenceItems != null) {
+    public void playSequentially(Animator... items) {
+        if (items != null) {
             mNeedsSort = true;
-            if (sequenceItems.length == 1) {
-                play(sequenceItems[0]);
+            if (items.length == 1) {
+                play(items[0]);
             } else {
-                for (int i = 0; i < sequenceItems.length - 1; ++i) {
-                    play(sequenceItems[i]).before(sequenceItems[i+1]);
+                for (int i = 0; i < items.length - 1; ++i) {
+                    play(items[i]).before(items[i+1]);
                 }
             }
         }
     }
 
     /**
-     * Returns the current list of child Animatable objects controlled by this
-     * Sequencer. This is a copy of the internal list; modifications to the returned list
-     * will not affect the Sequencer, although changes to the underlying Animatable objects
-     * will affect those objects being managed by the Sequencer.
+     * Returns the current list of child Animator objects controlled by this
+     * AnimatorSet. This is a copy of the internal list; modifications to the returned list
+     * will not affect the AnimatorSet, although changes to the underlying Animator objects
+     * will affect those objects being managed by the AnimatorSet.
      *
-     * @return ArrayList<Animatable> The list of child animations of this Sequencer.
+     * @return ArrayList<Animator> The list of child animations of this AnimatorSet.
      */
-    public ArrayList<Animatable> getChildAnimations() {
-        ArrayList<Animatable> childList = new ArrayList<Animatable>();
+    public ArrayList<Animator> getChildAnimations() {
+        ArrayList<Animator> childList = new ArrayList<Animator>();
         for (Node node : mNodes) {
             childList.add(node.animation);
         }
@@ -159,28 +155,28 @@
 
     /**
      * Sets the target object for all current {@link #getChildAnimations() child animations}
-     * of this Sequencer that take targets ({@link android.animation.PropertyAnimator} and
-     * Sequencer).
+     * of this AnimatorSet that take targets ({@link ObjectAnimator} and
+     * AnimatorSet).
      *
      * @param target The object being animated
      */
     @Override
     public void setTarget(Object target) {
         for (Node node : mNodes) {
-            Animatable animation = node.animation;
-            if (animation instanceof Sequencer) {
-                ((Sequencer)animation).setTarget(target);
-            } else if (animation instanceof PropertyAnimator) {
-                ((PropertyAnimator)animation).setTarget(target);
+            Animator animation = node.animation;
+            if (animation instanceof AnimatorSet) {
+                ((AnimatorSet)animation).setTarget(target);
+            } else if (animation instanceof ObjectAnimator) {
+                ((ObjectAnimator)animation).setTarget(target);
             }
         }
     }
 
     /**
      * Sets the Interpolator for all current {@link #getChildAnimations() child animations}
-     * of this Sequencer.
+     * of this AnimatorSet.
      *
-     * @param interpolator the interpolator to be used by each child animation of this Sequencer
+     * @param interpolator the interpolator to be used by each child animation of this AnimatorSet
      */
     @Override
     public void setInterpolator(Interpolator interpolator) {
@@ -194,11 +190,11 @@
      * set up playing constraints. This initial <code>play()</code> method
      * tells the <code>Builder</code> the animation that is the dependency for
      * the succeeding commands to the <code>Builder</code>. For example,
-     * calling <code>play(a1).with(a2)</code> sets up the Sequence to play
+     * calling <code>play(a1).with(a2)</code> sets up the AnimatorSet to play
      * <code>a1</code> and <code>a2</code> at the same time,
-     * <code>play(a1).before(a2)</code> sets up the Sequence to play
+     * <code>play(a1).before(a2)</code> sets up the AnimatorSet to play
      * <code>a1</code> first, followed by <code>a2</code>, and
-     * <code>play(a1).after(a2)</code> sets up the Sequence to play
+     * <code>play(a1).after(a2)</code> sets up the AnimatorSet to play
      * <code>a2</code> first, followed by <code>a1</code>.
      *
      * <p>Note that <code>play()</code> is the only way to tell the
@@ -213,11 +209,11 @@
      * @param anim The animation that is the dependency used in later calls to the
      * methods in the returned <code>Builder</code> object. A null parameter will result
      * in a null <code>Builder</code> return value.
-     * @return Builder The object that constructs the sequence based on the dependencies
+     * @return Builder The object that constructs the AnimatorSet based on the dependencies
      * outlined in the calls to <code>play</code> and the other methods in the
      * <code>Builder</code object.
      */
-    public Builder play(Animatable anim) {
+    public Builder play(Animator anim) {
         if (anim != null) {
             mNeedsSort = true;
             return new Builder(anim);
@@ -228,7 +224,7 @@
     /**
      * {@inheritDoc}
      *
-     * <p>Note that canceling a <code>Sequencer</code> also cancels all of the animations that it is
+     * <p>Note that canceling a <code>AnimatorSet</code> also cancels all of the animations that it is
      * responsible for.</p>
      */
     @SuppressWarnings("unchecked")
@@ -236,9 +232,9 @@
     public void cancel() {
         mCanceled = true;
         if (mListeners != null) {
-            ArrayList<AnimatableListener> tmpListeners =
-                    (ArrayList<AnimatableListener>) mListeners.clone();
-            for (AnimatableListener listener : tmpListeners) {
+            ArrayList<AnimatorListener> tmpListeners =
+                    (ArrayList<AnimatorListener>) mListeners.clone();
+            for (AnimatorListener listener : tmpListeners) {
                 listener.onAnimationCancel(this);
             }
         }
@@ -252,7 +248,7 @@
     /**
      * {@inheritDoc}
      *
-     * <p>Note that ending a <code>Sequencer</code> also ends all of the animations that it is
+     * <p>Note that ending a <code>AnimatorSet</code> also ends all of the animations that it is
      * responsible for.</p>
      */
     @Override
@@ -262,10 +258,10 @@
             // hasn't been started yet - sort the nodes now, then end them
             sortNodes();
             for (Node node : mSortedNodes) {
-                if (mSequenceListener == null) {
-                    mSequenceListener = new SequencerAnimatableListener(this);
+                if (mSetListener == null) {
+                    mSetListener = new AnimatorSetListener(this);
                 }
-                node.animation.addListener(mSequenceListener);
+                node.animation.addListener(mSetListener);
             }
         }
         if (mSortedNodes.size() > 0) {
@@ -276,9 +272,9 @@
     }
 
     /**
-     * Returns true if any of the child animations of this Sequencer have been started and have not
+     * Returns true if any of the child animations of this AnimatorSet have been started and have not
      * yet ended.
-     * @return Whether this Sequencer has been started and has not yet ended.
+     * @return Whether this AnimatorSet has been started and has not yet ended.
      */
     @Override
     public boolean isRunning() {
@@ -313,12 +309,12 @@
     }
 
     /**
-     * Gets the length of each of the child animations of this Sequencer. This value may
-     * be less than 0, which indicates that no duration has been set on this Sequencer
+     * Gets the length of each of the child animations of this AnimatorSet. This value may
+     * be less than 0, which indicates that no duration has been set on this AnimatorSet
      * and each of the child animations will use their own duration.
      *
      * @return The length of the animation, in milliseconds, of each of the child
-     * animations of this Sequencer.
+     * animations of this AnimatorSet.
      */
     @Override
     public long getDuration() {
@@ -326,12 +322,12 @@
     }
 
     /**
-     * Sets the length of each of the current child animations of this Sequencer. By default,
-     * each child animation will use its own duration. If the duration is set on the Sequencer,
+     * Sets the length of each of the current child animations of this AnimatorSet. By default,
+     * each child animation will use its own duration. If the duration is set on the AnimatorSet,
      * then each child animation inherits this duration.
      *
      * @param duration The length of the animation, in milliseconds, of each of the child
-     * animations of this Sequencer.
+     * animations of this AnimatorSet.
      */
     @Override
     public void setDuration(long duration) {
@@ -339,7 +335,7 @@
             throw new IllegalArgumentException("duration must be a value of zero or greater");
         }
         for (Node node : mNodes) {
-            // TODO: don't set the duration of the timing-only nodes created by Sequencer to
+            // TODO: don't set the duration of the timing-only nodes created by AnimatorSet to
             // insert "play-after" delays
             node.animation.setDuration(duration);
         }
@@ -349,7 +345,7 @@
     /**
      * {@inheritDoc}
      *
-     * <p>Starting this <code>Sequencer</code> will, in turn, start the animations for which
+     * <p>Starting this <code>AnimatorSet</code> will, in turn, start the animations for which
      * it is responsible. The details of when exactly those animations are started depends on
      * the dependency relationships that have been set up between the animations.
      */
@@ -368,8 +364,8 @@
         // when some other animation also wants to start when the first animation begins.
         final ArrayList<Node> nodesToStart = new ArrayList<Node>();
         for (Node node : mSortedNodes) {
-            if (mSequenceListener == null) {
-                mSequenceListener = new SequencerAnimatableListener(this);
+            if (mSetListener == null) {
+                mSetListener = new AnimatorSetListener(this);
             }
             if (node.dependencies == null || node.dependencies.size() == 0) {
                 nodesToStart.add(node);
@@ -380,7 +376,7 @@
                 }
                 node.tmpDependencies = (ArrayList<Dependency>) node.dependencies.clone();
             }
-            node.animation.addListener(mSequenceListener);
+            node.animation.addListener(mSetListener);
         }
         // Now that all dependencies are set up, start the animations that should be started.
         if (mStartDelay <= 0) {
@@ -390,9 +386,9 @@
             }
         } else {
             // TODO: Need to cancel out of the delay appropriately
-            Animator delayAnim = new Animator(mStartDelay, 0f, 1f);
-            delayAnim.addListener(new AnimatableListenerAdapter() {
-                public void onAnimationEnd(Animatable anim) {
+            ValueAnimator delayAnim = new ValueAnimator(mStartDelay, 0f, 1f);
+            delayAnim.addListener(new AnimatorListenerAdapter() {
+                public void onAnimationEnd(Animator anim) {
                     for (Node node : nodesToStart) {
                         node.animation.start();
                         mPlayingSet.add(node.animation);
@@ -401,20 +397,20 @@
             });
         }
         if (mListeners != null) {
-            ArrayList<AnimatableListener> tmpListeners =
-                    (ArrayList<AnimatableListener>) mListeners.clone();
-            for (AnimatableListener listener : tmpListeners) {
+            ArrayList<AnimatorListener> tmpListeners =
+                    (ArrayList<AnimatorListener>) mListeners.clone();
+            for (AnimatorListener listener : tmpListeners) {
                 listener.onAnimationStart(this);
             }
         }
     }
 
     @Override
-    public Sequencer clone() {
-        final Sequencer anim = (Sequencer) super.clone();
+    public AnimatorSet clone() {
+        final AnimatorSet anim = (AnimatorSet) super.clone();
         /*
          * The basic clone() operation copies all items. This doesn't work very well for
-         * Sequencer, because it will copy references that need to be recreated and state
+         * AnimatorSet, because it will copy references that need to be recreated and state
          * that may not apply. What we need to do now is put the clone in an uninitialized
          * state, with fresh, empty data structures. Then we will build up the nodes list
          * manually, as we clone each Node (and its animation). The clone will then be sorted,
@@ -422,13 +418,13 @@
          */
         anim.mNeedsSort = true;
         anim.mCanceled = false;
-        anim.mPlayingSet = new ArrayList<Animatable>();
-        anim.mNodeMap = new HashMap<Animatable, Node>();
+        anim.mPlayingSet = new ArrayList<Animator>();
+        anim.mNodeMap = new HashMap<Animator, Node>();
         anim.mNodes = new ArrayList<Node>();
         anim.mSortedNodes = new ArrayList<Node>();
 
         // Walk through the old nodes list, cloning each node and adding it to the new nodemap.
-        // One problem is that the old node dependencies point to nodes in the old sequencer.
+        // One problem is that the old node dependencies point to nodes in the old AnimatorSet.
         // We need to track the old/new nodes in order to reconstruct the dependencies in the clone.
         HashMap<Node, Node> nodeCloneMap = new HashMap<Node, Node>(); // <old, new>
         for (Node node : mNodes) {
@@ -441,21 +437,21 @@
             nodeClone.tmpDependencies = null;
             nodeClone.nodeDependents = null;
             nodeClone.nodeDependencies = null;
-            // clear out any listeners that were set up by the sequencer; these will
+            // clear out any listeners that were set up by the AnimatorSet; these will
             // be set up when the clone's nodes are sorted
-            ArrayList<AnimatableListener> cloneListeners = nodeClone.animation.getListeners();
+            ArrayList<AnimatorListener> cloneListeners = nodeClone.animation.getListeners();
             if (cloneListeners != null) {
-                ArrayList<AnimatableListener> listenersToRemove = null;
-                for (AnimatableListener listener : cloneListeners) {
-                    if (listener instanceof SequencerAnimatableListener) {
+                ArrayList<AnimatorListener> listenersToRemove = null;
+                for (AnimatorListener listener : cloneListeners) {
+                    if (listener instanceof AnimatorSetListener) {
                         if (listenersToRemove == null) {
-                            listenersToRemove = new ArrayList<AnimatableListener>();
+                            listenersToRemove = new ArrayList<AnimatorListener>();
                         }
                         listenersToRemove.add(listener);
                     }
                 }
                 if (listenersToRemove != null) {
-                    for (AnimatableListener listener : listenersToRemove) {
+                    for (AnimatorListener listener : listenersToRemove) {
                         cloneListeners.remove(listener);
                     }
                 }
@@ -483,9 +479,9 @@
      * animations. If an animation has multiple dependencies on other animations, then
      * all dependencies must be satisfied before the animation is started.
      */
-    private static class DependencyListener implements AnimatableListener {
+    private static class DependencyListener implements AnimatorListener {
 
-        private Sequencer mSequencer;
+        private AnimatorSet mAnimatorSet;
 
         // The node upon which the dependency is based.
         private Node mNode;
@@ -494,8 +490,8 @@
         // the node
         private int mRule;
 
-        public DependencyListener(Sequencer sequencer, Node node, int rule) {
-            this.mSequencer = sequencer;
+        public DependencyListener(AnimatorSet animatorSet, Node node, int rule) {
+            this.mAnimatorSet = animatorSet;
             this.mNode = node;
             this.mRule = rule;
         }
@@ -505,13 +501,13 @@
          * to prevent follow-on animations from running when some dependency
          * animation is canceled.
          */
-        public void onAnimationCancel(Animatable animation) {
+        public void onAnimationCancel(Animator animation) {
         }
 
         /**
          * An end event is received - see if this is an event we are listening for
          */
-        public void onAnimationEnd(Animatable animation) {
+        public void onAnimationEnd(Animator animation) {
             if (mRule == Dependency.AFTER) {
                 startIfReady(animation);
             }
@@ -520,13 +516,13 @@
         /**
          * Ignore repeat events for now
          */
-        public void onAnimationRepeat(Animatable animation) {
+        public void onAnimationRepeat(Animator animation) {
         }
 
         /**
          * A start event is received - see if this is an event we are listening for
          */
-        public void onAnimationStart(Animatable animation) {
+        public void onAnimationStart(Animator animation) {
             if (mRule == Dependency.WITH) {
                 startIfReady(animation);
             }
@@ -538,9 +534,9 @@
          * the animation.
          * @param dependencyAnimation the animation that sent the event.
          */
-        private void startIfReady(Animatable dependencyAnimation) {
-            if (mSequencer.mCanceled) {
-                // if the parent Sequencer was canceled, then don't start any dependent anims
+        private void startIfReady(Animator dependencyAnimation) {
+            if (mAnimatorSet.mCanceled) {
+                // if the parent AnimatorSet was canceled, then don't start any dependent anims
                 return;
             }
             Dependency dependencyToRemove = null;
@@ -558,37 +554,37 @@
             if (mNode.tmpDependencies.size() == 0) {
                 // all dependencies satisfied: start the animation
                 mNode.animation.start();
-                mSequencer.mPlayingSet.add(mNode.animation);
+                mAnimatorSet.mPlayingSet.add(mNode.animation);
             }
         }
 
     }
 
-    private class SequencerAnimatableListener implements AnimatableListener {
+    private class AnimatorSetListener implements AnimatorListener {
 
-        private Sequencer mSequencer;
+        private AnimatorSet mAnimatorSet;
 
-        SequencerAnimatableListener(Sequencer sequencer) {
-            mSequencer = sequencer;
+        AnimatorSetListener(AnimatorSet animatorSet) {
+            mAnimatorSet = animatorSet;
         }
 
-        public void onAnimationCancel(Animatable animation) {
+        public void onAnimationCancel(Animator animation) {
             if (mPlayingSet.size() == 0) {
                 if (mListeners != null) {
-                    for (AnimatableListener listener : mListeners) {
-                        listener.onAnimationCancel(mSequencer);
+                    for (AnimatorListener listener : mListeners) {
+                        listener.onAnimationCancel(mAnimatorSet);
                     }
                 }
             }
         }
 
         @SuppressWarnings("unchecked")
-        public void onAnimationEnd(Animatable animation) {
+        public void onAnimationEnd(Animator animation) {
             animation.removeListener(this);
             mPlayingSet.remove(animation);
-            Node animNode = mSequencer.mNodeMap.get(animation);
+            Node animNode = mAnimatorSet.mNodeMap.get(animation);
             animNode.done = true;
-            ArrayList<Node> sortedNodes = mSequencer.mSortedNodes;
+            ArrayList<Node> sortedNodes = mAnimatorSet.mSortedNodes;
             boolean allDone = true;
             for (Node node : sortedNodes) {
                 if (!node.done) {
@@ -598,23 +594,23 @@
             }
             if (allDone) {
                 // If this was the last child animation to end, then notify listeners that this
-                // sequencer has ended
+                // AnimatorSet has ended
                 if (mListeners != null) {
-                    ArrayList<AnimatableListener> tmpListeners =
-                            (ArrayList<AnimatableListener>) mListeners.clone();
-                    for (AnimatableListener listener : tmpListeners) {
-                        listener.onAnimationEnd(mSequencer);
+                    ArrayList<AnimatorListener> tmpListeners =
+                            (ArrayList<AnimatorListener>) mListeners.clone();
+                    for (AnimatorListener listener : tmpListeners) {
+                        listener.onAnimationEnd(mAnimatorSet);
                     }
                 }
             }
         }
 
         // Nothing to do
-        public void onAnimationRepeat(Animatable animation) {
+        public void onAnimationRepeat(Animator animation) {
         }
 
         // Nothing to do
-        public void onAnimationStart(Animatable animation) {
+        public void onAnimationStart(Animator animation) {
         }
 
     }
@@ -658,7 +654,7 @@
             mNeedsSort = false;
             if (mSortedNodes.size() != mNodes.size()) {
                 throw new IllegalStateException("Circular dependencies cannot exist"
-                        + " in Sequencer");
+                        + " in AnimatorSet");
             }
         } else {
             // Doesn't need sorting, but still need to add in the nodeDependencies list
@@ -702,13 +698,13 @@
     }
 
     /**
-     * A Node is an embodiment of both the Animatable that it wraps as well as
+     * A Node is an embodiment of both the Animator that it wraps as well as
      * any dependencies that are associated with that Animation. This includes
      * both dependencies upon other nodes (in the dependencies list) as
      * well as dependencies of other nodes upon this (in the nodeDependents list).
      */
     private static class Node implements Cloneable {
-        public Animatable animation;
+        public Animator animation;
 
         /**
          *  These are the dependencies that this node's animation has on other
@@ -723,8 +719,8 @@
          * But we also use the list to keep track of when multiple dependencies are satisfied,
          * but removing each dependency as it is satisfied. We do not want to remove
          * the dependency itself from the list, because we need to retain that information
-         * if the sequencer is launched in the future. So we create a copy of the dependency
-         * list when the sequencer starts and use this tmpDependencies list to track the
+         * if the AnimatorSet is launched in the future. So we create a copy of the dependency
+         * list when the AnimatorSet starts and use this tmpDependencies list to track the
          * list of satisfied dependencies.
          */
         public ArrayList<Dependency> tmpDependencies = null;
@@ -744,8 +740,8 @@
 
         /**
          * Flag indicating whether the animation in this node is finished. This flag
-         * is used by Sequencer to check, as each animation ends, whether all child animations
-         * are done and it's time to send out an end event for the entire Sequencer.
+         * is used by AnimatorSet to check, as each animation ends, whether all child animations
+         * are done and it's time to send out an end event for the entire AnimatorSet.
          */
         public boolean done = false;
 
@@ -756,7 +752,7 @@
          *
          * @param animation The animation that the Node encapsulates.
          */
-        public Node(Animatable animation) {
+        public Node(Animator animation) {
             this.animation = animation;
         }
 
@@ -785,7 +781,7 @@
         public Node clone() {
             try {
                 Node node = (Node) super.clone();
-                node.animation = (Animatable) animation.clone();
+                node.animation = (Animator) animation.clone();
                 return node;
             } catch (CloneNotSupportedException e) {
                throw new AssertionError();
@@ -795,45 +791,45 @@
 
     /**
      * The <code>Builder</code> object is a utility class to facilitate adding animations to a
-     * <code>Sequencer</code> along with the relationships between the various animations. The
+     * <code>AnimatorSet</code> along with the relationships between the various animations. The
      * intention of the <code>Builder</code> methods, along with the {@link
-     * Sequencer#play(Animatable) play()} method of <code>Sequencer</code> is to make it possible to
+     * AnimatorSet#play(Animator) play()} method of <code>AnimatorSet</code> is to make it possible to
      * express the dependency relationships of animations in a natural way. Developers can also use
-     * the {@link Sequencer#playTogether(Animatable[]) playTogether()} and {@link
-     * Sequencer#playSequentially(Animatable[]) playSequentially()} methods if these suit the need,
-     * but it might be easier in some situations to express the sequence of animations in pairs.
+     * the {@link AnimatorSet#playTogether(Animator[]) playTogether()} and {@link
+     * AnimatorSet#playSequentially(Animator[]) playSequentially()} methods if these suit the need,
+     * but it might be easier in some situations to express the AnimatorSet of animations in pairs.
      * <p/>
      * <p>The <code>Builder</code> object cannot be constructed directly, but is rather constructed
-     * internally via a call to {@link Sequencer#play(Animatable)}.</p>
+     * internally via a call to {@link AnimatorSet#play(Animator)}.</p>
      * <p/>
-     * <p>For example, this sets up a Sequencer to play anim1 and anim2 at the same time, anim3 to
+     * <p>For example, this sets up a AnimatorSet to play anim1 and anim2 at the same time, anim3 to
      * play when anim2 finishes, and anim4 to play when anim3 finishes:</p>
      * <pre>
-     *     Sequencer s = new Sequencer();
+     *     AnimatorSet s = new AnimatorSet();
      *     s.play(anim1).with(anim2);
      *     s.play(anim2).before(anim3);
      *     s.play(anim4).after(anim3);
      * </pre>
      * <p/>
-     * <p>Note in the example that both {@link Builder#before(Animatable)} and {@link
-     * Builder#after(Animatable)} are used. These are just different ways of expressing the same
+     * <p>Note in the example that both {@link Builder#before(Animator)} and {@link
+     * Builder#after(Animator)} are used. These are just different ways of expressing the same
      * relationship and are provided to make it easier to say things in a way that is more natural,
      * depending on the situation.</p>
      * <p/>
      * <p>It is possible to make several calls into the same <code>Builder</code> object to express
      * multiple relationships. However, note that it is only the animation passed into the initial
-     * {@link Sequencer#play(Animatable)} method that is the dependency in any of the successive
+     * {@link AnimatorSet#play(Animator)} method that is the dependency in any of the successive
      * calls to the <code>Builder</code> object. For example, the following code starts both anim2
      * and anim3 when anim1 ends; there is no direct dependency relationship between anim2 and
      * anim3:
      * <pre>
-     *   Sequencer s = new Sequencer();
+     *   AnimatorSet s = new AnimatorSet();
      *   s.play(anim1).before(anim2).before(anim3);
      * </pre>
      * If the desired result is to play anim1 then anim2 then anim3, this code expresses the
      * relationship correctly:</p>
      * <pre>
-     *   Sequencer s = new Sequencer();
+     *   AnimatorSet s = new AnimatorSet();
      *   s.play(anim1).before(anim2);
      *   s.play(anim2).before(anim3);
      * </pre>
@@ -841,26 +837,26 @@
      * <p>Note that it is possible to express relationships that cannot be resolved and will not
      * result in sensible results. For example, <code>play(anim1).after(anim1)</code> makes no
      * sense. In general, circular dependencies like this one (or more indirect ones where a depends
-     * on b, which depends on c, which depends on a) should be avoided. Only create sequences that
-     * can boil down to a simple, one-way relationship of animations starting with, before, and
+     * on b, which depends on c, which depends on a) should be avoided. Only create AnimatorSets
+     * that can boil down to a simple, one-way relationship of animations starting with, before, and
      * after other, different, animations.</p>
      */
     public class Builder {
 
         /**
          * This tracks the current node being processed. It is supplied to the play() method
-         * of Sequencer and passed into the constructor of Builder.
+         * of AnimatorSet and passed into the constructor of Builder.
          */
         private Node mCurrentNode;
 
         /**
-         * package-private constructor. Builders are only constructed by Sequencer, when the
+         * package-private constructor. Builders are only constructed by AnimatorSet, when the
          * play() method is called.
          *
          * @param anim The animation that is the dependency for the other animations passed into
          * the other methods of this Builder object.
          */
-        Builder(Animatable anim) {
+        Builder(Animator anim) {
             mCurrentNode = mNodeMap.get(anim);
             if (mCurrentNode == null) {
                 mCurrentNode = new Node(anim);
@@ -871,12 +867,12 @@
 
         /**
          * Sets up the given animation to play at the same time as the animation supplied in the
-         * {@link Sequencer#play(Animatable)} call that created this <code>Builder</code> object.
+         * {@link AnimatorSet#play(Animator)} call that created this <code>Builder</code> object.
          *
          * @param anim The animation that will play when the animation supplied to the
-         * {@link Sequencer#play(Animatable)} method starts.
+         * {@link AnimatorSet#play(Animator)} method starts.
          */
-        public void with(Animatable anim) {
+        public void with(Animator anim) {
             Node node = mNodeMap.get(anim);
             if (node == null) {
                 node = new Node(anim);
@@ -889,13 +885,13 @@
 
         /**
          * Sets up the given animation to play when the animation supplied in the
-         * {@link Sequencer#play(Animatable)} call that created this <code>Builder</code> object
+         * {@link AnimatorSet#play(Animator)} call that created this <code>Builder</code> object
          * ends.
          *
          * @param anim The animation that will play when the animation supplied to the
-         * {@link Sequencer#play(Animatable)} method ends.
+         * {@link AnimatorSet#play(Animator)} method ends.
          */
-        public void before(Animatable anim) {
+        public void before(Animator anim) {
             Node node = mNodeMap.get(anim);
             if (node == null) {
                 node = new Node(anim);
@@ -908,13 +904,13 @@
 
         /**
          * Sets up the given animation to play when the animation supplied in the
-         * {@link Sequencer#play(Animatable)} call that created this <code>Builder</code> object
+         * {@link AnimatorSet#play(Animator)} call that created this <code>Builder</code> object
          * to start when the animation supplied in this method call ends.
          *
          * @param anim The animation whose end will cause the animation supplied to the
-         * {@link Sequencer#play(Animatable)} method to play.
+         * {@link AnimatorSet#play(Animator)} method to play.
          */
-        public void after(Animatable anim) {
+        public void after(Animator anim) {
             Node node = mNodeMap.get(anim);
             if (node == null) {
                 node = new Node(anim);
@@ -927,15 +923,15 @@
 
         /**
          * Sets up the animation supplied in the
-         * {@link Sequencer#play(Animatable)} call that created this <code>Builder</code> object
+         * {@link AnimatorSet#play(Animator)} call that created this <code>Builder</code> object
          * to play when the given amount of time elapses.
          *
          * @param delay The number of milliseconds that should elapse before the
          * animation starts.
          */
         public void after(long delay) {
-            // setup dummy Animator just to run the clock
-            after(new Animator(delay, 0f, 1f));
+            // setup dummy ValueAnimator just to run the clock
+            after(new ValueAnimator(delay, 0f, 1f));
         }
 
     }
diff --git a/core/java/android/animation/Keyframe.java b/core/java/android/animation/Keyframe.java
index 7d4d104..192ba5c 100644
--- a/core/java/android/animation/Keyframe.java
+++ b/core/java/android/animation/Keyframe.java
@@ -20,7 +20,7 @@
 
 /**
  * This class holds a time/value pair for an animation. The Keyframe class is used
- * by {@link Animator} to define the values that the animation target will have over the course
+ * by {@link ValueAnimator} to define the values that the animation target will have over the course
  * of the animation. As the time proceeds from one keyframe to the other, the value of the
  * target object will animate between the value at the previous keyframe and the value at the
  * next keyframe. Each keyframe also holds an option {@link android.view.animation.Interpolator}
@@ -59,7 +59,7 @@
      * the time in this keyframe, and the the value animated from as the time passes the time in
      * this keyframe.
      * @param valueType The type of the <code>value</code> object. This is used by the
-     * {@link #getValue()} functionm, which is queried by {@link Animator} to determine
+     * {@link #getValue()} functionm, which is queried by {@link ValueAnimator} to determine
      * the type of {@link TypeEvaluator} to use to interpolate between values.
      */
     private Keyframe(float fraction, Object value, Class valueType) {
@@ -239,7 +239,7 @@
     }
 
     /**
-     * Gets the type of keyframe. This information is used by Animator to determine the type of
+     * Gets the type of keyframe. This information is used by ValueAnimator to determine the type of
      * {@link TypeEvaluator} to use when calculating values between keyframes. The type is based
      * on the type of Keyframe created.
      *
diff --git a/core/java/android/animation/KeyframeSet.java b/core/java/android/animation/KeyframeSet.java
index d144b9c..af47a15 100644
--- a/core/java/android/animation/KeyframeSet.java
+++ b/core/java/android/animation/KeyframeSet.java
@@ -21,7 +21,7 @@
 import android.view.animation.Interpolator;
 
 /**
- * This class holds a collection of Keyframe objects and is called by Animator to calculate
+ * This class holds a collection of Keyframe objects and is called by ValueAnimator to calculate
  * values between those keyframes for a given animation. The class internal to the animation
  * package because it is an implementation detail of how Keyframes are stored and used.
  */
diff --git a/core/java/android/animation/LayoutTransition.java b/core/java/android/animation/LayoutTransition.java
index 5dfdfbd..d1bc9bd 100644
--- a/core/java/android/animation/LayoutTransition.java
+++ b/core/java/android/animation/LayoutTransition.java
@@ -32,8 +32,8 @@
  * transitions for a layout container, create a LayoutTransition object and set it on any
  * ViewGroup by calling {@link ViewGroup#setLayoutTransition(LayoutTransition)}. This will cause
  * default animations to run whenever items are added to or removed from that container. To specify
- * custom animations, use the {@link LayoutTransition#setAnimatable(int, Animatable)
- * setAnimatable()} method.
+ * custom animations, use the {@link LayoutTransition#setAnimator(int, Animator)
+ * setAnimator()} method.
  *
  * <p>One of the core concepts of these transition animations is that there are two core
  * changes that cause the transition and four different animations that run because of
@@ -61,7 +61,7 @@
  * CHANGE_APPEARING animation animates <code>left</code>, <code>top</code>, <code>right</code>,
  * and <code>bottom</code>. Values for these properties are updated with the pre- and post-layout
  * values when the transition begins. Custom animations will be similarly populated with
- * the target and values being animated, assuming they use PropertyAnimator objects with
+ * the target and values being animated, assuming they use ObjectAnimator objects with
  * property names that are known on the target object.</p>
  */
 public class LayoutTransition {
@@ -93,21 +93,21 @@
     /**
      * These variables hold the animations that are currently used to run the transition effects.
      * These animations are set to defaults, but can be changed to custom animations by
-     * calls to setAnimatable().
+     * calls to setAnimator().
      */
-    private Animatable mDisappearingAnim = null;
-    private Animatable mAppearingAnim = null;
-    private Animatable mChangingAppearingAnim = null;
-    private Animatable mChangingDisappearingAnim = null;
+    private Animator mDisappearingAnim = null;
+    private Animator mAppearingAnim = null;
+    private Animator mChangingAppearingAnim = null;
+    private Animator mChangingDisappearingAnim = null;
 
     /**
      * These are the default animations, defined in the constructor, that will be used
      * unless the user specifies custom animations.
      */
-    private static PropertyAnimator defaultChangeIn;
-    private static PropertyAnimator defaultChangeOut;
-    private static PropertyAnimator defaultFadeIn;
-    private static PropertyAnimator defaultFadeOut;
+    private static ObjectAnimator defaultChangeIn;
+    private static ObjectAnimator defaultChangeOut;
+    private static ObjectAnimator defaultFadeIn;
+    private static ObjectAnimator defaultFadeOut;
 
     /**
      * The default duration used by all animations.
@@ -154,7 +154,7 @@
      * we cache all of the current animations in this map for possible cancellation on
      * another layout event.
      */
-    private HashMap<View, Animatable> currentAnimations = new HashMap<View, Animatable>();
+    private HashMap<View, Animator> currentAnimations = new HashMap<View, Animator>();
 
     /**
      * This hashmap is used to track the listeners that have been added to the children of
@@ -194,7 +194,7 @@
             PropertyValuesHolder<Integer> pvhTop = new PropertyValuesHolder<Integer>("top", 0, 1);
             PropertyValuesHolder<Integer> pvhRight = new PropertyValuesHolder<Integer>("right", 0, 1);
             PropertyValuesHolder<Integer> pvhBottom = new PropertyValuesHolder<Integer>("bottom", 0, 1);
-            defaultChangeIn = new PropertyAnimator<PropertyValuesHolder>(DEFAULT_DURATION, this,
+            defaultChangeIn = new ObjectAnimator<PropertyValuesHolder>(DEFAULT_DURATION, this,
                     pvhLeft, pvhTop, pvhRight, pvhBottom);
             defaultChangeIn.setStartDelay(mChangingAppearingDelay);
             defaultChangeIn.setInterpolator(mChangingAppearingInterpolator);
@@ -202,11 +202,11 @@
             defaultChangeOut.setStartDelay(mChangingDisappearingDelay);
             defaultChangeOut.setInterpolator(mChangingDisappearingInterpolator);
             defaultFadeIn =
-                    new PropertyAnimator<Float>(DEFAULT_DURATION, this, "alpha", 0f, 1f);
+                    new ObjectAnimator<Float>(DEFAULT_DURATION, this, "alpha", 0f, 1f);
             defaultFadeIn.setStartDelay(mAppearingDelay);
             defaultFadeIn.setInterpolator(mAppearingInterpolator);
             defaultFadeOut =
-                    new PropertyAnimator<Float>(DEFAULT_DURATION, this, "alpha", 1f, 0f);
+                    new ObjectAnimator<Float>(DEFAULT_DURATION, this, "alpha", 1f, 0f);
             defaultFadeOut.setStartDelay(mDisappearingDelay);
             defaultFadeOut.setInterpolator(mDisappearingInterpolator);
         }
@@ -240,7 +240,7 @@
      * {@link #APPEARING}, or {@link #DISAPPEARING}, which determines the animation whose start
      * delay is being set.
      * @param delay The length of time, in milliseconds, to delay before starting the animation.
-     * @see android.animation.Animatable#setStartDelay(long)
+     * @see Animator#setStartDelay(long)
      */
     public void setStartDelay(int transitionType, long delay) {
         switch (transitionType) {
@@ -268,7 +268,7 @@
      * {@link #APPEARING}, or {@link #DISAPPEARING}, which determines the animation whose start
      * delay is returned.
      * @return long The start delay of the specified animation.
-     * @see android.animation.Animatable#getStartDelay()
+     * @see Animator#getStartDelay()
      */
     public long getStartDelay(int transitionType) {
         switch (transitionType) {
@@ -294,7 +294,7 @@
      * {@link #APPEARING}, or {@link #DISAPPEARING}, which determines the animation whose
      * duration is being set.
      * @param duration The length of time, in milliseconds, that the specified animation should run.
-     * @see android.animation.Animatable#setDuration(long)
+     * @see Animator#setDuration(long)
      */
     public void setDuration(int transitionType, long duration) {
         switch (transitionType) {
@@ -322,7 +322,7 @@
      * {@link #APPEARING}, or {@link #DISAPPEARING}, which determines the animation whose
      * duration is returned.
      * @return long The duration of the specified animation.
-     * @see android.animation.Animatable#getDuration()
+     * @see Animator#getDuration()
      */
     public long getDuration(int transitionType) {
         switch (transitionType) {
@@ -387,7 +387,7 @@
      * {@link #APPEARING}, or {@link #DISAPPEARING}, which determines the animation whose
      * duration is being set.
      * @param interpolator The interpolator that the specified animation should use.
-     * @see android.animation.Animatable#setInterpolator(android.view.animation.Interpolator)
+     * @see Animator#setInterpolator(android.view.animation.Interpolator)
      */
     public void setInterpolator(int transitionType, Interpolator interpolator) {
         switch (transitionType) {
@@ -415,7 +415,7 @@
      * {@link #APPEARING}, or {@link #DISAPPEARING}, which determines the animation whose
      * duration is being set.
      * @return Interpolator The interpolator that the specified animation uses.
-     * @see android.animation.Animatable#setInterpolator(android.view.animation.Interpolator)
+     * @see Animator#setInterpolator(android.view.animation.Interpolator)
      */
     public Interpolator getInterpolator(int transitionType) {
         switch (transitionType) {
@@ -434,11 +434,11 @@
 
     /**
      * Sets the animation used during one of the transition types that may run. Any
-     * Animatable object can be used, but to be most useful in the context of layout
-     * transitions, the animation should either be a PropertyAnimator or a Sequencer
-     * of animations including PropertyAnimators. Also, these PropertyAnimator objects
+     * Animator object can be used, but to be most useful in the context of layout
+     * transitions, the animation should either be a ObjectAnimator or a AnimatorSet
+     * of animations including PropertyAnimators. Also, these ObjectAnimator objects
      * should be able to get and set values on their target objects automatically. For
-     * example, a PropertyAnimator that animates the property "left" is able to set and get the
+     * example, a ObjectAnimator that animates the property "left" is able to set and get the
      * <code>left</code> property from the View objects being animated by the layout
      * transition. The transition works by setting target objects and properties
      * dynamically, according to the pre- and post-layoout values of those objects, so
@@ -454,26 +454,26 @@
      * object (presumably 1) as its starting and ending value when the animation begins.
      * Animations which need to use values at the beginning and end that may not match the
      * values queried when the transition begins may need to use a different mechanism
-     * than a standard PropertyAnimator object.</p>
+     * than a standard ObjectAnimator object.</p>
      *
      * @param transitionType one of {@link #CHANGE_APPEARING}, {@link #CHANGE_DISAPPEARING},
      * {@link #APPEARING}, or {@link #DISAPPEARING}, which determines the animation whose
      * duration is being set.
-     * @param animatable The animation being assigned.
+     * @param animator The animation being assigned.
      */
-    public void setAnimatable(int transitionType, Animatable animatable) {
+    public void setAnimator(int transitionType, Animator animator) {
         switch (transitionType) {
             case CHANGE_APPEARING:
-                mChangingAppearingAnim = (animatable != null) ? animatable : defaultChangeIn;
+                mChangingAppearingAnim = (animator != null) ? animator : defaultChangeIn;
                 break;
             case CHANGE_DISAPPEARING:
-                mChangingDisappearingAnim = (animatable != null) ? animatable : defaultChangeOut;
+                mChangingDisappearingAnim = (animator != null) ? animator : defaultChangeOut;
                 break;
             case APPEARING:
-                mAppearingAnim = (animatable != null) ? animatable : defaultFadeIn;
+                mAppearingAnim = (animator != null) ? animator : defaultFadeIn;
                 break;
             case DISAPPEARING:
-                mDisappearingAnim = (animatable != null) ? animatable : defaultFadeOut;
+                mDisappearingAnim = (animator != null) ? animator : defaultFadeOut;
                 break;
         }
     }
@@ -484,10 +484,10 @@
      * @param transitionType one of {@link #CHANGE_APPEARING}, {@link #CHANGE_DISAPPEARING},
      * {@link #APPEARING}, or {@link #DISAPPEARING}, which determines the animation whose
      * duration is being set.
-     * @return Animatable The animation being used for the given transition type.
-     * @see #setAnimatable(int, Animatable)
+     * @return Animator The animation being used for the given transition type.
+     * @see #setAnimator(int, Animator)
      */
-    public Animatable getAnimatable(int transitionType) {
+    public Animator getAnimator(int transitionType) {
         switch (transitionType) {
             case CHANGE_APPEARING:
                 return mChangingAppearingAnim;
@@ -529,21 +529,21 @@
             if (child != newView) {
 
                 // If there's an animation running on this view already, cancel it
-                Animatable currentAnimation = currentAnimations.get(child);
+                Animator currentAnimation = currentAnimations.get(child);
                 if (currentAnimation != null) {
                     currentAnimation.cancel();
                     currentAnimations.remove(child);
                 }
 
                 // Make a copy of the appropriate animation
-                final Animatable anim = (changeReason == APPEARING) ?
+                final Animator anim = (changeReason == APPEARING) ?
                         mChangingAppearingAnim.clone() :
                         mChangingDisappearingAnim.clone();
 
                 // Set the target object for the animation
                 anim.setTarget(child);
 
-                // A PropertyAnimator (or Sequencer of them) can extract start values from
+                // A ObjectAnimator (or AnimatorSet of them) can extract start values from
                 // its target object
                 anim.setupStartValues();
 
@@ -574,20 +574,20 @@
                         anim.setDuration(duration);
 
                         // Remove the animation from the cache when it ends
-                        anim.addListener(new AnimatableListenerAdapter() {
+                        anim.addListener(new AnimatorListenerAdapter() {
                             private boolean canceled = false;
-                            public void onAnimationCancel(Animatable animatable) {
+                            public void onAnimationCancel(Animator animator) {
                                 // we remove canceled animations immediately, not here
                                 canceled = true;
                             }
-                            public void onAnimationEnd(Animatable animatable) {
+                            public void onAnimationEnd(Animator animator) {
                                 if (!canceled) {
                                     currentAnimations.remove(child);
                                 }
                             }
                         });
-                        if (anim instanceof PropertyAnimator) {
-                            ((PropertyAnimator) anim).setCurrentPlayTime(0);
+                        if (anim instanceof ObjectAnimator) {
+                            ((ObjectAnimator) anim).setCurrentPlayTime(0);
                         }
                         anim.start();
 
@@ -626,15 +626,15 @@
      * @param child The View being added to the ViewGroup.
      */
     private void runAppearingTransition(final ViewGroup parent, final View child) {
-        Animatable anim = mAppearingAnim.clone();
+        Animator anim = mAppearingAnim.clone();
         anim.setTarget(child);
         anim.setStartDelay(mAppearingDelay);
         anim.setDuration(mAppearingDuration);
-        if (anim instanceof PropertyAnimator) {
-            ((PropertyAnimator) anim).setCurrentPlayTime(0);
+        if (anim instanceof ObjectAnimator) {
+            ((ObjectAnimator) anim).setCurrentPlayTime(0);
         }
         if (mListeners != null) {
-            anim.addListener(new AnimatableListenerAdapter() {
+            anim.addListener(new AnimatorListenerAdapter() {
                 public void onAnimationEnd() {
                     for (TransitionListener listener : mListeners) {
                         listener.endTransition(LayoutTransition.this, parent, child, APPEARING);
@@ -652,12 +652,12 @@
      * @param child The View being removed from the ViewGroup.
      */
     private void runDisappearingTransition(final ViewGroup parent, final View child) {
-        Animatable anim = mDisappearingAnim.clone();
+        Animator anim = mDisappearingAnim.clone();
         anim.setStartDelay(mDisappearingDelay);
         anim.setDuration(mDisappearingDuration);
         anim.setTarget(child);
         if (mListeners != null) {
-            anim.addListener(new AnimatableListenerAdapter() {
+            anim.addListener(new AnimatorListenerAdapter() {
                 public void onAnimationEnd() {
                     for (TransitionListener listener : mListeners) {
                         listener.endTransition(LayoutTransition.this, parent, child, DISAPPEARING);
@@ -665,8 +665,8 @@
                 }
             });
         }
-        if (anim instanceof PropertyAnimator) {
-            ((PropertyAnimator) anim).setCurrentPlayTime(0);
+        if (anim instanceof ObjectAnimator) {
+            ((ObjectAnimator) anim).setCurrentPlayTime(0);
         }
         anim.start();
     }
diff --git a/core/java/android/animation/PropertyAnimator.java b/core/java/android/animation/ObjectAnimator.java
similarity index 92%
rename from core/java/android/animation/PropertyAnimator.java
rename to core/java/android/animation/ObjectAnimator.java
index e555cc6..6cb90be 100644
--- a/core/java/android/animation/PropertyAnimator.java
+++ b/core/java/android/animation/ObjectAnimator.java
@@ -21,13 +21,13 @@
 import java.lang.reflect.Method;
 
 /**
- * This subclass of {@link Animator} provides support for animating properties on target objects.
+ * This subclass of {@link ValueAnimator} provides support for animating properties on target objects.
  * The constructors of this class take parameters to define the target object that will be animated
  * as well as the name of the property that will be animated. Appropriate set/get functions
  * are then determined internally and the animation will call these functions as necessary to
  * animate the property.
  */
-public final class PropertyAnimator<T> extends Animator<T> {
+public final class ObjectAnimator<T> extends ValueAnimator<T> {
 
     // The target object on which the property exists, set in the constructor
     private Object mTarget;
@@ -47,7 +47,7 @@
      * <code>valueFrom</code> and <code>valueTo</code> properties, otherwise the call to
      * the setter function will fail.</p>
      *
-     * <p>If this PropertyAnimator has been set up to animate several properties together,
+     * <p>If this ObjectAnimator has been set up to animate several properties together,
      * using more than one PropertyValuesHolder objects, then setting the propertyName simply
      * sets the propertyName in the first of those PropertyValuesHolder objects.</p>
      *
@@ -101,18 +101,18 @@
         try {
             returnVal = mTarget.getClass().getMethod(setterName, args);
         } catch (NoSuchMethodException e) {
-            Log.e("PropertyAnimator",
+            Log.e("ObjectAnimator",
                     "Couldn't find setter/getter for property " + mPropertyName + ": " + e);
         }
         return returnVal;
     }
 
     /**
-     * Creates a new PropertyAnimator object. This default constructor is primarily for
+     * Creates a new ObjectAnimator object. This default constructor is primarily for
      * use internally; the other constructors which take parameters are more generally
      * useful.
      */
-    public PropertyAnimator() {
+    public ObjectAnimator() {
     }
 
     /**
@@ -128,7 +128,7 @@
      * is assumed to be the final value being animated to, and the initial value will be
      * derived on the fly.
      */
-    public PropertyAnimator(long duration, Object target, String propertyName, T...values) {
+    public ObjectAnimator(long duration, Object target, String propertyName, T...values) {
         super(duration, (T[]) values);
         mTarget = target;
         setPropertyName(propertyName);
@@ -136,7 +136,7 @@
 
     /**
      * A constructor that takes <code>PropertyValueHolder</code> values. This constructor should
-     * be used when animating several properties at once with the same PropertyAnimator, since
+     * 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.
      *
@@ -148,7 +148,7 @@
      * @param values The PropertyValuesHolder objects which hold each the property name and values
      * to animate that property between.
      */
-    public PropertyAnimator(long duration, Object target, PropertyValuesHolder...values) {
+    public ObjectAnimator(long duration, Object target, PropertyValuesHolder...values) {
         super(duration);
         setValues(values);
         mTarget = target;
@@ -239,8 +239,8 @@
     }
 
     @Override
-    public PropertyAnimator clone() {
-        final PropertyAnimator anim = (PropertyAnimator) super.clone();
+    public ObjectAnimator clone() {
+        final ObjectAnimator anim = (ObjectAnimator) super.clone();
         return anim;
     }
 }
diff --git a/core/java/android/animation/PropertyValuesHolder.java b/core/java/android/animation/PropertyValuesHolder.java
index b6ff54e..1d46123 100644
--- a/core/java/android/animation/PropertyValuesHolder.java
+++ b/core/java/android/animation/PropertyValuesHolder.java
@@ -27,31 +27,31 @@
 /**
  * This class holds information about a property and the values that that property
  * should take on during an animation. PropertyValuesHolder objects can be used to create
- * animations with Animator or PropertyAnimator that operate on several different properties
+ * animations with ValueAnimator or ObjectAnimator that operate on several different properties
  * in parallel.
  */
 public class PropertyValuesHolder<T> implements Cloneable {
 
     /**
      * The name of the property associated with the values. This need not be a real property,
-     * unless this object is being used with PropertyAnimator. But this is the name by which
-     * aniamted values are looked up with getAnimatedValue(String) in Animator.
+     * unless this object is being used with ObjectAnimator. But this is the name by which
+     * aniamted values are looked up with getAnimatedValue(String) in ValueAnimator.
      */
     private String mPropertyName;
 
     /**
-     * The setter function, if needed. PropertyAnimator hands off this functionality to
+     * The setter function, if needed. ObjectAnimator hands off this functionality to
      * PropertyValuesHolder, since it holds all of the per-property information. This
      * property can be manually set via setSetter(). Otherwise, it is automatically
-     * derived when the animation starts in setupSetterAndGetter() if using PropertyAnimator.
+     * derived when the animation starts in setupSetterAndGetter() if using ObjectAnimator.
      */
     private Method mSetter = null;
 
     /**
-     * The getter function, if needed. PropertyAnimator hands off this functionality to
+     * The getter function, if needed. ObjectAnimator hands off this functionality to
      * PropertyValuesHolder, since it holds all of the per-property information. This
      * property can be manually set via setSetter(). Otherwise, it is automatically
-     * derived when the animation starts in setupSetterAndGetter() if using PropertyAnimator.
+     * derived when the animation starts in setupSetterAndGetter() if using ObjectAnimator.
      * The getter is only derived and used if one of the values is null.
      */
     private Method mGetter = null;
@@ -112,16 +112,16 @@
 
     /**
      * The value most recently calculated by calculateValue(). This is set during
-     * that function and might be retrieved later either by Animator.animatedValue() or
-     * by the property-setting logic in PropertyAnimator.animatedValue().
+     * that function and might be retrieved later either by ValueAnimator.animatedValue() or
+     * by the property-setting logic in ObjectAnimator.animatedValue().
      */
     private Object mAnimatedValue;
 
     /**
      * Constructs a PropertyValuesHolder object with just a set of values. This constructor
-     * is typically not used when animating objects with PropertyAnimator, because that
+     * is typically not used when animating objects with ObjectAnimator, because that
      * object needs distinct and meaningful property names. Simpler animations of one
-     * set of values using Animator may use this constructor, however, because no
+     * set of values using ValueAnimator may use this constructor, however, because no
      * distinguishing name is needed.
      * @param values The set of values to animate between. If there is only one value, it
      * is assumed to be the final value being animated to, and the initial value will be
@@ -141,14 +141,14 @@
      * on the object. 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
-     * {@link android.animation.PropertyAnimator}, and with a getter function either
+     * {@link ObjectAnimator}, and with a getter function either
      * derived automatically from <code>propertyName</code> or set explicitly via
      * {@link #setGetter(java.lang.reflect.Method)}, since otherwise PropertyValuesHolder has
      * no way of determining what the value should be.
      * @param propertyName The name of the property associated with this set of values. This
-     * can be the actual property name to be used when using a PropertyAnimator object, or
+     * can be the actual property name to be used when using a ObjectAnimator object, or
      * just a name used to get animated values, such as if this object is used with an
-     * Animator object.
+     * ValueAnimator object.
      * @param values The set of values to animate between.
      */
     public PropertyValuesHolder(String propertyName, T... values) {
@@ -163,7 +163,7 @@
      * on the object. 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
-     * {@link android.animation.PropertyAnimator}, and with a getter function either
+     * {@link ObjectAnimator}, and with a getter function either
      * derived automatically from <code>propertyName</code> or set explicitly via
      * {@link #setGetter(java.lang.reflect.Method)}, since otherwise PropertyValuesHolder has
      * no way of determining what the value should be.
@@ -331,7 +331,7 @@
     }
 
     /**
-     * Internal function (called from PropertyAnimator) to set up the setter and getter
+     * Internal function (called from ObjectAnimator) to set up the setter and getter
      * prior to running the animation. If the setter has not been manually set for this
      * object, it will be derived automatically given the property name, target object, and
      * types of values supplied. If no getter has been set, it will be supplied iff any of the
@@ -383,7 +383,7 @@
     }
 
     /**
-     * This function is called by PropertyAnimator when setting the start values for an animation.
+     * This function is called by ObjectAnimator when setting the start values for an animation.
      * The start values are set according to the current values in the target object. The
      * property whose value is extracted is whatever is specified by the propertyName of this
      * PropertyValuesHolder object.
@@ -395,7 +395,7 @@
     }
 
     /**
-     * This function is called by PropertyAnimator when setting the end values for an animation.
+     * This function is called by ObjectAnimator when setting the end values for an animation.
      * The end values are set according to the current values in the target object. The
      * property whose value is extracted is whatever is specified by the propertyName of this
      * PropertyValuesHolder object.
@@ -420,8 +420,8 @@
     }
     /**
      * Internal function to set the value on the target object, using the setter set up
-     * earlier on this PropertyValuesHolder object. This function is called by PropertyAnimator
-     * to handle turning the value calculated by Animator into a value set on the object
+     * earlier on this PropertyValuesHolder object. This function is called by ObjectAnimator
+     * to handle turning the value calculated by ValueAnimator into a value set on the object
      * according to the name of the property.
      * @param target The target object on which the value is set
      */
@@ -439,7 +439,7 @@
     }
 
     /**
-     * Internal function, called by Animator, to set up the TypeEvaluator that will be used
+     * Internal function, called by ValueAnimator, to set up the TypeEvaluator that will be used
      * to calculate animated values.
      */
     void init() {
@@ -466,7 +466,7 @@
 
     /**
      * Function used to calculate the value according to the evaluator set up for
-     * this PropertyValuesHolder object. This function is called by Animator.animateValue().
+     * this PropertyValuesHolder object. This function is called by ValueAnimator.animateValue().
      *
      * @param fraction The elapsed, interpolated fraction of the animation.
      * @return The calculated value at this point in the animation.
@@ -483,7 +483,7 @@
      * approach is more direct, and is especially useful when a function must be called that does
      * not correspond to the convention of <code>setName()</code>. For example, if a function
      * called <code>offset()</code> is to be called with the animated values, there is no way
-     * to tell <code>PropertyAnimator</code> how to call that function simply through a property
+     * to tell <code>ObjectAnimator</code> how to call that function simply through a property
      * name, so a setter method should be supplied instead.
      *
      * <p>Note that the setter function must take the same parameter type as the
@@ -511,7 +511,7 @@
      * approach is more direct, and is especially useful when a function must be called that does
      * not correspond to the convention of <code>setName()</code>. For example, if a function
      * called <code>offset()</code> is to be called to get an initial value, there is no way
-     * to tell <code>PropertyAnimator</code> how to call that function simply through a property
+     * to tell <code>ObjectAnimator</code> how to call that function simply through a property
      * name, so a getter method should be supplied instead.
      *
      * <p>Note that the getter method is only called whether supplied here or derived
@@ -569,7 +569,7 @@
     }
 
     /**
-     * Internal function, called by Animator and PropertyAnimator, to retrieve the value
+     * Internal function, called by ValueAnimator and ObjectAnimator, to retrieve the value
      * most recently calculated in calculateValue().
      * @return
      */
diff --git a/core/java/android/animation/TypeEvaluator.java b/core/java/android/animation/TypeEvaluator.java
index 6150e00..fa49175 100644
--- a/core/java/android/animation/TypeEvaluator.java
+++ b/core/java/android/animation/TypeEvaluator.java
@@ -17,12 +17,12 @@
 package android.animation;
 
 /**
- * Interface for use with the {@link Animator#setEvaluator(TypeEvaluator)} function. Evaluators
+ * Interface for use with the {@link ValueAnimator#setEvaluator(TypeEvaluator)} function. Evaluators
  * allow developers to create animations on arbitrary property types, by allowing them to supply
  * custom evaulators for types that are not automatically understood and used by the animation
  * system.
  *
- * @see Animator#setEvaluator(TypeEvaluator)
+ * @see ValueAnimator#setEvaluator(TypeEvaluator)
  */
 public interface TypeEvaluator {
 
diff --git a/core/java/android/animation/ValueAnimator.java b/core/java/android/animation/ValueAnimator.java
new file mode 100755
index 0000000..54a8e4b
--- /dev/null
+++ b/core/java/android/animation/ValueAnimator.java
@@ -0,0 +1,972 @@
+/*
+ * Copyright (C) 2010 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.animation;
+
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.view.animation.AccelerateDecelerateInterpolator;
+import android.view.animation.AnimationUtils;
+import android.view.animation.Interpolator;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+
+/**
+ * This class provides a simple timing engine for running animations
+ * which calculate animated values and set them on target objects.
+ *
+ * <p>There is a single timing pulse that all animations use. It runs in a
+ * custom handler to ensure that property changes happen on the UI thread.</p>
+ *
+ * <p>By default, ValueAnimator uses non-linear time interpolation, via the
+ * {@link AccelerateDecelerateInterpolator} class, which accelerates into and decelerates
+ * out of an animation. This behavior can be changed by calling
+ * {@link ValueAnimator#setInterpolator(Interpolator)}.</p>
+ */
+public class ValueAnimator<T> extends Animator {
+
+    /**
+     * Internal constants
+     */
+
+    /*
+     * The default amount of time in ms between animation frames
+     */
+    private static final long DEFAULT_FRAME_DELAY = 30;
+
+    /**
+     * Messages sent to timing handler: START is sent when an animation first begins, FRAME is sent
+     * by the handler to itself to process the next animation frame
+     */
+    private static final int ANIMATION_START = 0;
+    private static final int ANIMATION_FRAME = 1;
+
+    /**
+     * Values used with internal variable mPlayingState to indicate the current state of an
+     * animation.
+     */
+    private static final int STOPPED    = 0; // Not yet playing
+    private static final int RUNNING    = 1; // Playing normally
+    private static final int CANCELED   = 2; // cancel() called - need to end it
+    private static final int ENDED      = 3; // end() called - need to end it
+    private static final int SEEKED     = 4; // Seeked to some time value
+
+    /**
+     * Internal variables
+     * NOTE: This object implements the clone() method, making a deep copy of any referenced
+     * objects. As other non-trivial fields are added to this class, make sure to add logic
+     * to clone() to make deep copies of them.
+     */
+
+    // The first time that the animation's animateFrame() method is called. This time is used to
+    // determine elapsed time (and therefore the elapsed fraction) in subsequent calls
+    // to animateFrame()
+    private long mStartTime;
+
+    /**
+     * Set when setCurrentPlayTime() is called. If negative, animation is not currently seeked
+     * to a value.
+     */
+    private long mSeekTime = -1;
+
+    // The static sAnimationHandler processes the internal timing loop on which all animations
+    // are based
+    private static AnimationHandler sAnimationHandler;
+
+    // The static list of all active animations
+    private static final ArrayList<ValueAnimator> sAnimations = new ArrayList<ValueAnimator>();
+
+    // The set of animations to be started on the next animation frame
+    private static final ArrayList<ValueAnimator> sPendingAnimations = new ArrayList<ValueAnimator>();
+
+    // The time interpolator to be used if none is set on the animation
+    private static final Interpolator sDefaultInterpolator = new AccelerateDecelerateInterpolator();
+
+    // type evaluators for the three primitive types handled by this implementation
+    private static final TypeEvaluator sIntEvaluator = new IntEvaluator();
+    private static final TypeEvaluator sFloatEvaluator = new FloatEvaluator();
+    private static final TypeEvaluator sDoubleEvaluator = new DoubleEvaluator();
+
+    /**
+     * Used to indicate whether the animation is currently playing in reverse. This causes the
+     * elapsed fraction to be inverted to calculate the appropriate values.
+     */
+    private boolean mPlayingBackwards = false;
+
+    /**
+     * This variable tracks the current iteration that is playing. When mCurrentIteration exceeds the
+     * repeatCount (if repeatCount!=INFINITE), the animation ends
+     */
+    private int mCurrentIteration = 0;
+
+    /**
+     * Tracks whether a startDelay'd animation has begun playing through the startDelay.
+     */
+    private boolean mStartedDelay = false;
+
+    /**
+     * Tracks the time at which the animation began playing through its startDelay. This is
+     * different from the mStartTime variable, which is used to track when the animation became
+     * active (which is when the startDelay expired and the animation was added to the active
+     * animations list).
+     */
+    private long mDelayStartTime;
+
+    /**
+     * Flag that represents the current state of the animation. Used to figure out when to start
+     * an animation (if state == STOPPED). Also used to end an animation that
+     * has been cancel()'d or end()'d since the last animation frame. Possible values are
+     * STOPPED, RUNNING, ENDED, CANCELED.
+     */
+    private int mPlayingState = STOPPED;
+
+    /**
+     * Internal collections used to avoid set collisions as animations start and end while being
+     * processed.
+     */
+    private static final ArrayList<ValueAnimator> sEndingAnims = new ArrayList<ValueAnimator>();
+    private static final ArrayList<ValueAnimator> sDelayedAnims = new ArrayList<ValueAnimator>();
+    private static final ArrayList<ValueAnimator> sReadyAnims = new ArrayList<ValueAnimator>();
+
+    /**
+     * Flag that denotes whether the animation is set up and ready to go. Used to
+     * set up animation that has not yet been started.
+     */
+    boolean mInitialized = false;
+
+    //
+    // Backing variables
+    //
+
+    // How long the animation should last in ms
+    private long mDuration;
+
+    // The amount of time in ms to delay starting the animation after start() is called
+    private long mStartDelay = 0;
+
+    // The number of milliseconds between animation frames
+    private static long sFrameDelay = DEFAULT_FRAME_DELAY;
+
+    // The number of times the animation will repeat. The default is 0, which means the animation
+    // will play only once
+    private int mRepeatCount = 0;
+
+    /**
+     * The type of repetition that will occur when repeatMode is nonzero. RESTART means the
+     * animation will start from the beginning on every new cycle. REVERSE means the animation
+     * will reverse directions on each iteration.
+     */
+    private int mRepeatMode = RESTART;
+
+    /**
+     * The time interpolator to be used. The elapsed fraction of the animation will be passed
+     * through this interpolator to calculate the interpolated fraction, which is then used to
+     * calculate the animated values.
+     */
+    private Interpolator mInterpolator = sDefaultInterpolator;
+
+    /**
+     * The set of listeners to be sent events through the life of an animation.
+     */
+    private ArrayList<AnimatorUpdateListener> mUpdateListeners = null;
+
+    /**
+     * The property/value sets being animated.
+     */
+    PropertyValuesHolder[] mValues;
+
+    /**
+     * A hashmap of the PropertyValuesHolder objects. This map is used to lookup animated values
+     * by property name during calls to getAnimatedValue(String).
+     */
+    HashMap<String, PropertyValuesHolder> mValuesMap;
+
+    /**
+     * Public constants
+     */
+
+    /**
+     * When the animation reaches the end and <code>repeatCount</code> is INFINITE
+     * or a positive value, the animation restarts from the beginning.
+     */
+    public static final int RESTART = 1;
+    /**
+     * When the animation reaches the end and <code>repeatCount</code> is INFINITE
+     * or a positive value, the animation reverses direction on every iteration.
+     */
+    public static final int REVERSE = 2;
+    /**
+     * This value used used with the {@link #setRepeatCount(int)} property to repeat
+     * the animation indefinitely.
+     */
+    public static final int INFINITE = -1;
+
+    /**
+     * Creates a new ValueAnimator object. This default constructor is primarily for
+     * use internally; the other constructors which take parameters are more generally
+     * useful.
+     */
+    public ValueAnimator() {
+    }
+
+    /**
+     * Constructs an ValueAnimator object with the specified duration and set of
+     * values. If the values are a set of PropertyValuesHolder objects, then these objects
+     * define the potentially multiple properties being animated and the values the properties are
+     * animated between. Otherwise, the values define a single set of values animated between.
+     *
+     * @param duration The length of the animation, in milliseconds.
+     * @param values The set of values to animate between. If these values are not
+     * PropertyValuesHolder objects, then there should be more than one value, since the values
+     * determine the interval to animate between.
+     */
+    public ValueAnimator(long duration, T...values) {
+        mDuration = duration;
+        if (values.length > 0) {
+            setValues(values);
+        }
+    }
+
+    /**
+     * Sets the values, per property, being animated between. This function is called internally
+     * by the constructors of ValueAnimator that take a list of values. But an ValueAnimator can
+     * be constructed without values and this method can be called to set the values manually
+     * instead.
+     *
+     * @param values The set of values, per property, being animated between.
+     */
+    public void setValues(PropertyValuesHolder... values) {
+        int numValues = values.length;
+        mValues = values;
+        mValuesMap = new HashMap<String, PropertyValuesHolder>(numValues);
+        for (int i = 0; i < numValues; ++i) {
+            PropertyValuesHolder valuesHolder = (PropertyValuesHolder) values[i];
+            mValuesMap.put(valuesHolder.getPropertyName(), valuesHolder);
+        }
+    }
+
+    /**
+     * Returns the values that this ValueAnimator animates between. These values are stored in
+     * PropertyValuesHolder objects, even if the ValueAnimator was created with a simple list
+     * of value objects instead.
+     *
+     * @return PropertyValuesHolder[] An array of PropertyValuesHolder objects which hold the
+     * values, per property, that define the animation.
+     */
+    public PropertyValuesHolder[] getValues() {
+        return mValues;
+    }
+
+    /**
+     * Sets the values to animate between for this animation. If <code>values</code> is
+     * a set of PropertyValuesHolder objects, these objects will become the set of properties
+     * animated and the values that those properties are animated between. Otherwise, this method
+     * will set only one set of values for the ValueAnimator. Also, if the values are not
+     * PropertyValuesHolder objects and if there are already multiple sets of
+     * values defined for this ValueAnimator via
+     * more than one PropertyValuesHolder objects, this method will set the values for
+     * the first of those objects.
+     *
+     * @param values The set of values to animate between.
+     */
+    public void setValues(T... values) {
+        if (mValues == null || mValues.length == 0) {
+            setValues(new PropertyValuesHolder[]{
+                    new PropertyValuesHolder("", (Object[])values)});
+        } else {
+            PropertyValuesHolder valuesHolder = mValues[0];
+            valuesHolder.setValues(values);
+        }
+    }
+
+    /**
+     * This function is called immediately before processing the first animation
+     * frame of an animation. If there is a nonzero <code>startDelay</code>, the
+     * function is called after that delay ends.
+     * It takes care of the final initialization steps for the
+     * animation.
+     *
+     *  <p>Overrides of this method should call the superclass method to ensure
+     *  that internal mechanisms for the animation are set up correctly.</p>
+     */
+    void initAnimation() {
+        if (!mInitialized) {
+            int numValues = mValues.length;
+            for (int i = 0; i < numValues; ++i) {
+                mValues[i].init();
+            }
+            mCurrentIteration = 0;
+            mInitialized = true;
+        }
+    }
+
+
+    /**
+     * Sets the length of the animation.
+     *
+     * @param duration The length of the animation, in milliseconds.
+     */
+    public void setDuration(long duration) {
+        mDuration = duration;
+    }
+
+    /**
+     * Gets the length of the animation.
+     *
+     * @return The length of the animation, in milliseconds.
+     */
+    public long getDuration() {
+        return mDuration;
+    }
+
+    /**
+     * Sets the position of the animation to the specified point in time. This time should
+     * be between 0 and the total duration of the animation, including any repetition. If
+     * the animation has not yet been started, then it will not advance forward after it is
+     * set to this time; it will simply set the time to this value and perform any appropriate
+     * actions based on that time. If the animation is already running, then setCurrentPlayTime()
+     * will set the current playing time to this value and continue playing from that point.
+     *
+     * @param playTime The time, in milliseconds, to which the animation is advanced or rewound.
+     */
+    public void setCurrentPlayTime(long playTime) {
+        initAnimation();
+        long currentTime = AnimationUtils.currentAnimationTimeMillis();
+        if (mPlayingState != RUNNING) {
+            mSeekTime = playTime;
+            mPlayingState = SEEKED;
+        }
+        mStartTime = currentTime - playTime;
+        animationFrame(currentTime);
+    }
+
+    /**
+     * Gets the current position of the animation in time, which is equal to the current
+     * time minus the time that the animation started. An animation that is not yet started will
+     * return a value of zero.
+     *
+     * @return The current position in time of the animation.
+     */
+    public long getCurrentPlayTime() {
+        if (!mInitialized || mPlayingState == STOPPED) {
+            return 0;
+        }
+        return AnimationUtils.currentAnimationTimeMillis() - mStartTime;
+    }
+
+    /**
+     * This custom, static handler handles the timing pulse that is shared by
+     * all active animations. This approach ensures that the setting of animation
+     * values will happen on the UI thread and that all animations will share
+     * the same times for calculating their values, which makes synchronizing
+     * animations possible.
+     *
+     */
+    private static class AnimationHandler extends Handler {
+        /**
+         * There are only two messages that we care about: ANIMATION_START and
+         * ANIMATION_FRAME. The START message is sent when an animation's start()
+         * method is called. It cannot start synchronously when start() is called
+         * because the call may be on the wrong thread, and it would also not be
+         * synchronized with other animations because it would not start on a common
+         * timing pulse. So each animation sends a START message to the handler, which
+         * causes the handler to place the animation on the active animations queue and
+         * start processing frames for that animation.
+         * The FRAME message is the one that is sent over and over while there are any
+         * active animations to process.
+         */
+        @Override
+        public void handleMessage(Message msg) {
+            boolean callAgain = true;
+            switch (msg.what) {
+                // TODO: should we avoid sending frame message when starting if we
+                // were already running?
+                case ANIMATION_START:
+                    if (sAnimations.size() > 0 || sDelayedAnims.size() > 0) {
+                        callAgain = false;
+                    }
+                    // pendingAnims holds any animations that have requested to be started
+                    // We're going to clear sPendingAnimations, but starting animation may
+                    // cause more to be added to the pending list (for example, if one animation
+                    // starting triggers another starting). So we loop until sPendingAnimations
+                    // is empty.
+                    while (sPendingAnimations.size() > 0) {
+                        ArrayList<ValueAnimator> pendingCopy =
+                                (ArrayList<ValueAnimator>) sPendingAnimations.clone();
+                        sPendingAnimations.clear();
+                        int count = pendingCopy.size();
+                        for (int i = 0; i < count; ++i) {
+                            ValueAnimator anim = pendingCopy.get(i);
+                            // If the animation has a startDelay, place it on the delayed list
+                            if (anim.mStartDelay == 0 || anim.mPlayingState == ENDED ||
+                                    anim.mPlayingState == CANCELED) {
+                                anim.startAnimation();
+                            } else {
+                                sDelayedAnims.add(anim);
+                            }
+                        }
+                    }
+                    // fall through to process first frame of new animations
+                case ANIMATION_FRAME:
+                    // currentTime holds the common time for all animations processed
+                    // during this frame
+                    long currentTime = AnimationUtils.currentAnimationTimeMillis();
+
+                    // First, process animations currently sitting on the delayed queue, adding
+                    // them to the active animations if they are ready
+                    int numDelayedAnims = sDelayedAnims.size();
+                    for (int i = 0; i < numDelayedAnims; ++i) {
+                        ValueAnimator anim = sDelayedAnims.get(i);
+                        if (anim.delayedAnimationFrame(currentTime)) {
+                            sReadyAnims.add(anim);
+                        }
+                    }
+                    int numReadyAnims = sReadyAnims.size();
+                    if (numReadyAnims > 0) {
+                        for (int i = 0; i < numReadyAnims; ++i) {
+                            ValueAnimator anim = sReadyAnims.get(i);
+                            anim.startAnimation();
+                            sDelayedAnims.remove(anim);
+                        }
+                        sReadyAnims.clear();
+                    }
+
+                    // Now process all active animations. The return value from animationFrame()
+                    // tells the handler whether it should now be ended
+                    int numAnims = sAnimations.size();
+                    for (int i = 0; i < numAnims; ++i) {
+                        ValueAnimator anim = sAnimations.get(i);
+                        if (anim.animationFrame(currentTime)) {
+                            sEndingAnims.add(anim);
+                        }
+                    }
+                    if (sEndingAnims.size() > 0) {
+                        for (int i = 0; i < sEndingAnims.size(); ++i) {
+                            sEndingAnims.get(i).endAnimation();
+                        }
+                        sEndingAnims.clear();
+                    }
+
+                    // If there are still active or delayed animations, call the handler again
+                    // after the frameDelay
+                    if (callAgain && (!sAnimations.isEmpty() || !sDelayedAnims.isEmpty())) {
+                        sendEmptyMessageDelayed(ANIMATION_FRAME, sFrameDelay);
+                    }
+                    break;
+            }
+        }
+    }
+
+    /**
+     * The amount of time, in milliseconds, to delay starting the animation after
+     * {@link #start()} is called.
+     *
+     * @return the number of milliseconds to delay running the animation
+     */
+    public long getStartDelay() {
+        return mStartDelay;
+    }
+
+    /**
+     * The amount of time, in milliseconds, to delay starting the animation after
+     * {@link #start()} is called.
+
+     * @param startDelay The amount of the delay, in milliseconds
+     */
+    public void setStartDelay(long startDelay) {
+        this.mStartDelay = startDelay;
+    }
+
+    /**
+     * The amount of time, in milliseconds, between each frame of the animation. This is a
+     * requested time that the animation will attempt to honor, but the actual delay between
+     * frames may be different, depending on system load and capabilities. This is a static
+     * function because the same delay will be applied to all animations, since they are all
+     * run off of a single timing loop.
+     *
+     * @return the requested time between frames, in milliseconds
+     */
+    public static long getFrameDelay() {
+        return sFrameDelay;
+    }
+
+    /**
+     * The amount of time, in milliseconds, between each frame of the animation. This is a
+     * requested time that the animation will attempt to honor, but the actual delay between
+     * frames may be different, depending on system load and capabilities. This is a static
+     * function because the same delay will be applied to all animations, since they are all
+     * run off of a single timing loop.
+     *
+     * @param frameDelay the requested time between frames, in milliseconds
+     */
+    public static void setFrameDelay(long frameDelay) {
+        sFrameDelay = frameDelay;
+    }
+
+    /**
+     * The most recent value calculated by this <code>ValueAnimator</code> when there is just one
+     * property being animated. This value is only sensible while the animation is running. The main
+     * purpose for this read-only property is to retrieve the value from the <code>ValueAnimator</code>
+     * during a call to {@link AnimatorUpdateListener#onAnimationUpdate(ValueAnimator)}, which
+     * is called during each animation frame, immediately after the value is calculated.
+     *
+     * @return animatedValue The value most recently calculated by this <code>ValueAnimator</code> for
+     * the single property being animated. If there are several properties being animated
+     * (specified by several PropertyValuesHolder objects in the constructor), this function
+     * returns the animated value for the first of those objects.
+     */
+    public Object getAnimatedValue() {
+        if (mValues != null && mValues.length > 0) {
+            return mValues[0].getAnimatedValue();
+        }
+        // Shouldn't get here; should always have values unless ValueAnimator was set up wrong
+        return null;
+    }
+
+    /**
+     * The most recent value calculated by this <code>ValueAnimator</code> for <code>propertyName</code>.
+     * The main purpose for this read-only property is to retrieve the value from the
+     * <code>ValueAnimator</code> during a call to
+     * {@link AnimatorUpdateListener#onAnimationUpdate(ValueAnimator)}, which
+     * is called during each animation frame, immediately after the value is calculated.
+     *
+     * @return animatedValue The value most recently calculated for the named property
+     * by this <code>ValueAnimator</code>.
+     */
+    public Object getAnimatedValue(String propertyName) {
+        PropertyValuesHolder valuesHolder = mValuesMap.get(propertyName);
+        if (valuesHolder != null) {
+            return valuesHolder.getAnimatedValue();
+        } else {
+            // At least avoid crashing if called with bogus propertyName
+            return null;
+        }
+    }
+
+    /**
+     * Sets how many times the animation should be repeated. If the repeat
+     * count is 0, the animation is never repeated. If the repeat count is
+     * greater than 0 or {@link #INFINITE}, the repeat mode will be taken
+     * into account. The repeat count is 0 by default.
+     *
+     * @param value the number of times the animation should be repeated
+     */
+    public void setRepeatCount(int value) {
+        mRepeatCount = value;
+    }
+    /**
+     * Defines how many times the animation should repeat. The default value
+     * is 0.
+     *
+     * @return the number of times the animation should repeat, or {@link #INFINITE}
+     */
+    public int getRepeatCount() {
+        return mRepeatCount;
+    }
+
+    /**
+     * Defines what this animation should do when it reaches the end. This
+     * setting is applied only when the repeat count is either greater than
+     * 0 or {@link #INFINITE}. Defaults to {@link #RESTART}.
+     *
+     * @param value {@link #RESTART} or {@link #REVERSE}
+     */
+    public void setRepeatMode(int value) {
+        mRepeatMode = value;
+    }
+
+    /**
+     * Defines what this animation should do when it reaches the end.
+     *
+     * @return either one of {@link #REVERSE} or {@link #RESTART}
+     */
+    public int getRepeatMode() {
+        return mRepeatMode;
+    }
+
+    /**
+     * Adds a listener to the set of listeners that are sent update events through the life of
+     * an animation. This method is called on all listeners for every frame of the animation,
+     * after the values for the animation have been calculated.
+     *
+     * @param listener the listener to be added to the current set of listeners for this animation.
+     */
+    public void addUpdateListener(AnimatorUpdateListener listener) {
+        if (mUpdateListeners == null) {
+            mUpdateListeners = new ArrayList<AnimatorUpdateListener>();
+        }
+        mUpdateListeners.add(listener);
+    }
+
+    /**
+     * Removes a listener from the set listening to frame updates for this animation.
+     *
+     * @param listener the listener to be removed from the current set of update listeners
+     * for this animation.
+     */
+    public void removeUpdateListener(AnimatorUpdateListener listener) {
+        if (mUpdateListeners == null) {
+            return;
+        }
+        mUpdateListeners.remove(listener);
+        if (mUpdateListeners.size() == 0) {
+            mUpdateListeners = null;
+        }
+    }
+
+
+    /**
+     * The time interpolator used in calculating the elapsed fraction of this animation. The
+     * interpolator determines whether the animation runs with linear or non-linear motion,
+     * such as acceleration and deceleration. The default value is
+     * {@link android.view.animation.AccelerateDecelerateInterpolator}
+     *
+     * @param value the interpolator to be used by this animation
+     */
+    @Override
+    public void setInterpolator(Interpolator value) {
+        if (value != null) {
+            mInterpolator = value;
+        }
+    }
+
+    /**
+     * Returns the timing interpolator that this ValueAnimator uses.
+     *
+     * @return The timing interpolator for this ValueAnimator.
+     */
+    public Interpolator getInterpolator() {
+        return mInterpolator;
+    }
+
+    /**
+     * The type evaluator to be used when calculating the animated values of this animation.
+     * The system will automatically assign a float, int, or double evaluator based on the type
+     * of <code>startValue</code> and <code>endValue</code> in the constructor. But if these values
+     * are not one of these primitive types, or if different evaluation is desired (such as is
+     * necessary with int values that represent colors), a custom evaluator needs to be assigned.
+     * For example, when running an animation on color values, the {@link RGBEvaluator}
+     * should be used to get correct RGB color interpolation.
+     *
+     * <p>If this ValueAnimator has only one set of values being animated between, this evaluator
+     * will be used for that set. If there are several sets of values being animated, which is
+     * the case if PropertyValuesHOlder objects were set on the ValueAnimator, then the evaluator
+     * is assigned just to the first PropertyValuesHolder object.</p>
+     *
+     * @param value the evaluator to be used this animation
+     */
+    public void setEvaluator(TypeEvaluator value) {
+        if (value != null && mValues != null && mValues.length > 0) {
+            mValues[0].setEvaluator(value);
+        }
+    }
+
+    /**
+     * Start the animation playing. This version of start() takes a boolean flag that indicates
+     * whether the animation should play in reverse. The flag is usually false, but may be set
+     * to true if called from the reverse() method/
+     *
+     * @param playBackwards Whether the ValueAnimator should start playing in reverse.
+     */
+    private void start(boolean playBackwards) {
+        mPlayingBackwards = playBackwards;
+        if ((mStartDelay == 0) && (Thread.currentThread() == Looper.getMainLooper().getThread())) {
+            // This sets the initial value of the animation, prior to actually starting it running
+            setCurrentPlayTime(getCurrentPlayTime());
+        }
+        mPlayingState = STOPPED;
+        mStartedDelay = false;
+        sPendingAnimations.add(this);
+        if (sAnimationHandler == null) {
+            sAnimationHandler = new AnimationHandler();
+        }
+        // TODO: does this put too many messages on the queue if the handler
+        // is already running?
+        sAnimationHandler.sendEmptyMessage(ANIMATION_START);
+    }
+
+    @Override
+    public void start() {
+        start(false);
+    }
+
+    @Override
+    public void cancel() {
+        if (mListeners != null) {
+            ArrayList<AnimatorListener> tmpListeners =
+                    (ArrayList<AnimatorListener>) mListeners.clone();
+            for (AnimatorListener listener : tmpListeners) {
+                listener.onAnimationCancel(this);
+            }
+        }
+        // Just set the CANCELED flag - this causes the animation to end the next time a frame
+        // is processed.
+        mPlayingState = CANCELED;
+    }
+
+    @Override
+    public void end() {
+        if (!sAnimations.contains(this) && !sPendingAnimations.contains(this)) {
+            // Special case if the animation has not yet started; get it ready for ending
+            mStartedDelay = false;
+            sPendingAnimations.add(this);
+            if (sAnimationHandler == null) {
+                sAnimationHandler = new AnimationHandler();
+            }
+            sAnimationHandler.sendEmptyMessage(ANIMATION_START);
+        }
+        // Just set the ENDED flag - this causes the animation to end the next time a frame
+        // is processed.
+        mPlayingState = ENDED;
+    }
+
+    @Override
+    public boolean isRunning() {
+        // ENDED or CANCELED indicate that it has been ended or canceled, but not processed yet
+        return (mPlayingState == RUNNING || mPlayingState == ENDED || mPlayingState == CANCELED);
+    }
+
+    /**
+     * Plays the ValueAnimator in reverse. If the animation is already running,
+     * it will stop itself and play backwards from the point reached when reverse was called.
+     * If the animation is not currently running, then it will start from the end and
+     * play backwards. This behavior is only set for the current animation; future playing
+     * of the animation will use the default behavior of playing forward.
+     */
+    public void reverse() {
+        mPlayingBackwards = !mPlayingBackwards;
+        if (mPlayingState == RUNNING) {
+            long currentTime = AnimationUtils.currentAnimationTimeMillis();
+            long currentPlayTime = currentTime - mStartTime;
+            long timeLeft = mDuration - currentPlayTime;
+            mStartTime = currentTime - timeLeft;
+        } else {
+            start(true);
+        }
+    }
+
+    /**
+     * Called internally to end an animation by removing it from the animations list. Must be
+     * called on the UI thread.
+     */
+    private void endAnimation() {
+        sAnimations.remove(this);
+        mPlayingState = STOPPED;
+        if (mListeners != null) {
+            ArrayList<AnimatorListener> tmpListeners =
+                    (ArrayList<AnimatorListener>) mListeners.clone();
+            for (AnimatorListener listener : tmpListeners) {
+                listener.onAnimationEnd(this);
+            }
+        }
+    }
+
+    /**
+     * Called internally to start an animation by adding it to the active animations list. Must be
+     * called on the UI thread.
+     */
+    private void startAnimation() {
+        initAnimation();
+        sAnimations.add(this);
+        if (mListeners != null) {
+            ArrayList<AnimatorListener> tmpListeners =
+                    (ArrayList<AnimatorListener>) mListeners.clone();
+            for (AnimatorListener listener : tmpListeners) {
+                listener.onAnimationStart(this);
+            }
+        }
+    }
+
+    /**
+     * Internal function called to process an animation frame on an animation that is currently
+     * sleeping through its <code>startDelay</code> phase. The return value indicates whether it
+     * should be woken up and put on the active animations queue.
+     *
+     * @param currentTime The current animation time, used to calculate whether the animation
+     * has exceeded its <code>startDelay</code> and should be started.
+     * @return True if the animation's <code>startDelay</code> has been exceeded and the animation
+     * should be added to the set of active animations.
+     */
+    private boolean delayedAnimationFrame(long currentTime) {
+        if (mPlayingState == CANCELED || mPlayingState == ENDED) {
+            // end the delay, process an animation frame to actually cancel it
+            return true;
+        }
+        if (!mStartedDelay) {
+            mStartedDelay = true;
+            mDelayStartTime = currentTime;
+        } else {
+            long deltaTime = currentTime - mDelayStartTime;
+            if (deltaTime > mStartDelay) {
+                // startDelay ended - start the anim and record the
+                // mStartTime appropriately
+                mStartTime = currentTime - (deltaTime - mStartDelay);
+                mPlayingState = RUNNING;
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * This internal function processes a single animation frame for a given animation. The
+     * currentTime parameter is the timing pulse sent by the handler, used to calculate the
+     * elapsed duration, and therefore
+     * the elapsed fraction, of the animation. The return value indicates whether the animation
+     * should be ended (which happens when the elapsed time of the animation exceeds the
+     * animation's duration, including the repeatCount).
+     *
+     * @param currentTime The current time, as tracked by the static timing handler
+     * @return true if the animation's duration, including any repetitions due to
+     * <code>repeatCount</code> has been exceeded and the animation should be ended.
+     */
+    private boolean animationFrame(long currentTime) {
+        boolean done = false;
+
+        if (mPlayingState == STOPPED) {
+            mPlayingState = RUNNING;
+            if (mSeekTime < 0) {
+                mStartTime = currentTime;
+            } else {
+                mStartTime = currentTime - mSeekTime;
+                // Now that we're playing, reset the seek time
+                mSeekTime = -1;
+            }
+        }
+        switch (mPlayingState) {
+        case RUNNING:
+        case SEEKED:
+            float fraction = (float)(currentTime - mStartTime) / mDuration;
+            if (fraction >= 1f) {
+                if (mCurrentIteration < mRepeatCount || mRepeatCount == INFINITE) {
+                    // Time to repeat
+                    if (mListeners != null) {
+                        for (AnimatorListener listener : mListeners) {
+                            listener.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;
+                    mStartTime += mDuration;
+                } else {
+                    done = true;
+                    fraction = Math.min(fraction, 1.0f);
+                }
+            }
+            if (mPlayingBackwards) {
+                fraction = 1f - fraction;
+            }
+            animateValue(fraction);
+            break;
+        case ENDED:
+            // The final value set on the target varies, depending on whether the animation
+            // was supposed to repeat an odd number of times
+            if (mRepeatCount > 0 && (mRepeatCount & 0x01) == 1) {
+                animateValue(0f);
+            } else {
+                animateValue(1f);
+            }
+            // Fall through to set done flag
+        case CANCELED:
+            done = true;
+            mPlayingState = STOPPED;
+            break;
+        }
+
+        return done;
+    }
+
+    /**
+     * This method is called with the elapsed fraction of the animation during every
+     * animation frame. This function turns the elapsed fraction into an interpolated fraction
+     * and then into an animated value (from the evaluator. The function is called mostly during
+     * animation updates, but it is also called when the <code>end()</code>
+     * function is called, to set the final value on the property.
+     *
+     * <p>Overrides of this method must call the superclass to perform the calculation
+     * of the animated value.</p>
+     *
+     * @param fraction The elapsed fraction of the animation.
+     */
+    void animateValue(float fraction) {
+        fraction = mInterpolator.getInterpolation(fraction);
+        int numValues = mValues.length;
+        for (int i = 0; i < numValues; ++i) {
+            mValues[i].calculateValue(fraction);
+        }
+        if (mUpdateListeners != null) {
+            int numListeners = mUpdateListeners.size();
+            for (int i = 0; i < numListeners; ++i) {
+                mUpdateListeners.get(i).onAnimationUpdate(this);
+            }
+        }
+    }
+
+    @Override
+    public ValueAnimator clone() {
+        final ValueAnimator anim = (ValueAnimator) super.clone();
+        if (mUpdateListeners != null) {
+            ArrayList<AnimatorUpdateListener> oldListeners = mUpdateListeners;
+            anim.mUpdateListeners = new ArrayList<AnimatorUpdateListener>();
+            int numListeners = oldListeners.size();
+            for (int i = 0; i < numListeners; ++i) {
+                anim.mUpdateListeners.add(oldListeners.get(i));
+            }
+        }
+        anim.mSeekTime = -1;
+        anim.mPlayingBackwards = false;
+        anim.mCurrentIteration = 0;
+        anim.mInitialized = false;
+        anim.mPlayingState = STOPPED;
+        anim.mStartedDelay = false;
+        PropertyValuesHolder[] oldValues = mValues;
+        if (oldValues != null) {
+            int numValues = oldValues.length;
+            anim.mValues = new PropertyValuesHolder[numValues];
+            for (int i = 0; i < numValues; ++i) {
+                anim.mValues[i] = oldValues[i].clone();
+            }
+            anim.mValuesMap = new HashMap<String, PropertyValuesHolder>(numValues);
+            for (int i = 0; i < numValues; ++i) {
+                PropertyValuesHolder valuesHolder = mValues[i];
+                anim.mValuesMap.put(valuesHolder.getPropertyName(), valuesHolder);
+            }
+        }
+        return anim;
+    }
+
+    /**
+     * Implementors of this interface can add themselves as update listeners
+     * to an <code>ValueAnimator</code> instance to receive callbacks on every animation
+     * frame, after the current frame's values have been calculated for that
+     * <code>ValueAnimator</code>.
+     */
+    public static interface AnimatorUpdateListener {
+        /**
+         * <p>Notifies the occurrence of another frame of the animation.</p>
+         *
+         * @param animation The animation which was repeated.
+         */
+        void onAnimationUpdate(ValueAnimator animation);
+
+    }
+}
\ No newline at end of file
diff --git a/core/java/android/app/ActionBar.java b/core/java/android/app/ActionBar.java
index 38086f0..29f2e30 100644
--- a/core/java/android/app/ActionBar.java
+++ b/core/java/android/app/ActionBar.java
@@ -123,72 +123,6 @@
     public abstract int getSelectedNavigationItem();
 
     /**
-     * Set the action bar into standard navigation mode, supplying a title and subtitle.
-     * 
-     * Standard navigation mode is default. The title is automatically set to the
-     * name of your Activity. Subtitles are displayed underneath the title, usually
-     * in a smaller font or otherwise less prominently than the title. Subtitles are
-     * good for extended descriptions of activity state.
-     *
-     * @param title The action bar's title. null is treated as an empty string.
-     * @param subtitle The action bar's subtitle. null will remove the subtitle entirely.
-     *
-     * @see #setStandardNavigationMode()
-     * @see #setStandardNavigationMode(CharSequence)
-     * @see #setStandardNavigationMode(int)
-     * @see #setStandardNavigationMode(int, int)
-     */
-    public abstract void setStandardNavigationMode(CharSequence title, CharSequence subtitle);
-
-    /**
-     * Set the action bar into standard navigation mode, supplying a title and subtitle.
-     * 
-     * Standard navigation mode is default. The title is automatically set to the
-     * name of your Activity. Subtitles are displayed underneath the title, usually
-     * in a smaller font or otherwise less prominently than the title. Subtitles are
-     * good for extended descriptions of activity state.
-     *
-     * @param titleResId Resource ID of a title string
-     * @param subtitleResId Resource ID of a subtitle string
-     *
-     * @see #setStandardNavigationMode()
-     * @see #setStandardNavigationMode(CharSequence)
-     * @see #setStandardNavigationMode(CharSequence, CharSequence)
-     * @see #setStandardNavigationMode(int)
-     */
-    public abstract void setStandardNavigationMode(int titleResId, int subtitleResId);
-
-    /**
-     * Set the action bar into standard navigation mode, supplying a title and subtitle.
-     * 
-     * Standard navigation mode is default. The title is automatically set to the
-     * name of your Activity on startup if an action bar is present.
-     *
-     * @param title The action bar's title. null is treated as an empty string.
-     *
-     * @see #setStandardNavigationMode()
-     * @see #setStandardNavigationMode(CharSequence, CharSequence)
-     * @see #setStandardNavigationMode(int)
-     * @see #setStandardNavigationMode(int, int)
-     */
-    public abstract void setStandardNavigationMode(CharSequence title);
-
-    /**
-     * Set the action bar into standard navigation mode, supplying a title and subtitle.
-     * 
-     * Standard navigation mode is default. The title is automatically set to the
-     * name of your Activity on startup if an action bar is present.
-     *
-     * @param titleResId Resource ID of a title string
-     *
-     * @see #setStandardNavigationMode()
-     * @see #setStandardNavigationMode(CharSequence)
-     * @see #setStandardNavigationMode(CharSequence, CharSequence)
-     * @see #setStandardNavigationMode(int, int)
-     */
-    public abstract void setStandardNavigationMode(int titleResId);
-
-    /**
      * Set the action bar into standard navigation mode, using the currently set title
      * and/or subtitle.
      *
@@ -324,18 +258,6 @@
     public abstract void setTabNavigationMode();
 
     /**
-     * Set the action bar into tabbed navigation mode.
-     *
-     * @param containerViewId Id of the container view where tab content fragments should appear.
-     *
-     * @see #addTab(Tab)
-     * @see #insertTab(Tab, int)
-     * @see #removeTab(Tab)
-     * @see #removeTabAt(int)
-     */
-    public abstract void setTabNavigationMode(int containerViewId);
-
-    /**
      * Create and return a new {@link Tab}.
      * This tab will not be included in the action bar until it is added.
      *
@@ -354,13 +276,13 @@
     public abstract void addTab(Tab tab);
 
     /**
-     * Insert a tab for use in tabbed navigation mode. The tab will be inserted at
+     * Add a tab for use in tabbed navigation mode. The tab will be inserted at
      * <code>position</code>.
      *
      * @param tab The tab to add
      * @param position The new position of the tab
      */
-    public abstract void insertTab(Tab tab, int position);
+    public abstract void addTab(Tab tab, int position);
 
     /**
      * Remove a tab from the action bar.
@@ -384,6 +306,14 @@
     public abstract void selectTab(Tab tab);
 
     /**
+     * Returns the currently selected tab if in tabbed navigation mode and there is at least
+     * one tab present.
+     *
+     * @return The currently selected tab or null
+     */
+    public abstract Tab getSelectedTab();
+
+    /**
      * Retrieve the current height of the ActionBar.
      *
      * @return The ActionBar's height
@@ -477,22 +407,68 @@
         public abstract void setText(CharSequence text);
 
         /**
-         * Returns the fragment that will be shown when this tab is selected.
+         * Set a custom view to be used for this tab. This overrides values set by
+         * {@link #setText(CharSequence)} and {@link #setIcon(Drawable)}.
          *
-         * @return Fragment associated with this tab
+         * @param view Custom view to be used as a tab.
          */
-        public abstract Fragment getFragment();
+        public abstract void setCustomView(View view);
 
         /**
-         * Set the fragment that will be shown when this tab is selected.
+         * Retrieve a previously set custom view for this tab.
          *
-         * @param fragment Fragment to associate with this tab
+         * @return The custom view set by {@link #setCustomView(View)}.
          */
-        public abstract void setFragment(Fragment fragment);
+        public abstract View getCustomView();
+
+        /**
+         * Give this Tab an arbitrary object to hold for later use.
+         *
+         * @param obj Object to store
+         */
+        public abstract void setTag(Object obj);
+
+        /**
+         * @return This Tab's tag object.
+         */
+        public abstract Object getTag();
+
+        /**
+         * Set the {@link TabListener} that will handle switching to and from this tab.
+         * All tabs must have a TabListener set before being added to the ActionBar.
+         *
+         * @param listener Listener to handle tab selection events
+         */
+        public abstract void setTabListener(TabListener listener);
 
         /**
          * Select this tab. Only valid if the tab has been added to the action bar.
          */
         public abstract void select();
     }
+
+    /**
+     * Callback interface invoked when a tab is focused, unfocused, added, or removed.
+     */
+    public interface TabListener {
+        /**
+         * Called when a tab enters the selected state.
+         *
+         * @param tab The tab that was selected
+         * @param ft A {@link FragmentTransaction} for queuing fragment operations to execute
+         *        during a tab switch. The previous tab's unselect and this tab's select will be
+         *        executed in a single transaction.
+         */
+        public void onTabSelected(Tab tab, FragmentTransaction ft);
+
+        /**
+         * Called when a tab exits the selected state.
+         *
+         * @param tab The tab that was unselected
+         * @param ft A {@link FragmentTransaction} for queuing fragment operations to execute
+         *        during a tab switch. This tab's unselect and the newly selected tab's select
+         *        will be executed in a single transaction.
+         */
+        public void onTabUnselected(Tab tab, FragmentTransaction ft);
+    }
 }
diff --git a/core/java/android/app/BackStackEntry.java b/core/java/android/app/BackStackEntry.java
index 00c2fc4..71fd5e5 100644
--- a/core/java/android/app/BackStackEntry.java
+++ b/core/java/android/app/BackStackEntry.java
@@ -490,4 +490,8 @@
     public int getTransitionStyle() {
         return mTransitionStyle;
     }
+
+    public boolean isEmpty() {
+        return mNumOp == 0;
+    }
 }
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 6886aba..7497136 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -323,54 +323,54 @@
     @Override
     public SharedPreferences getSharedPreferences(String name, int mode) {
         SharedPreferencesImpl sp;
+        File prefsFile;
+        boolean needInitialLoad = false;
         synchronized (sSharedPrefs) {
             sp = sSharedPrefs.get(name);
-            if (sp != null && !sp.hasFileChanged()) {
-                //Log.i(TAG, "Returning existing prefs " + name + ": " + sp);
+            if (sp != null && !sp.hasFileChangedUnexpectedly()) {
                 return sp;
             }
-        }
-        File f = getSharedPrefsFile(name);
-        FileInputStream str = null;
-        File backup = makeBackupFile(f);
-        if (backup.exists()) {
-            f.delete();
-            backup.renameTo(f);
-        }
-
-        // Debugging
-        if (f.exists() && !f.canRead()) {
-            Log.w(TAG, "Attempt to read preferences file " + f + " without permission");
-        }
-
-        Map map = null;
-        if (f.exists() && f.canRead()) {
-            try {
-                str = new FileInputStream(f);
-                map = XmlUtils.readMapXml(str);
-                str.close();
-            } catch (org.xmlpull.v1.XmlPullParserException e) {
-                Log.w(TAG, "getSharedPreferences", e);
-            } catch (FileNotFoundException e) {
-                Log.w(TAG, "getSharedPreferences", e);
-            } catch (IOException e) {
-                Log.w(TAG, "getSharedPreferences", e);
+            prefsFile = getSharedPrefsFile(name);
+            if (sp == null) {
+                sp = new SharedPreferencesImpl(prefsFile, mode, null);
+                sSharedPrefs.put(name, sp);
+                needInitialLoad = true;
             }
         }
 
-        synchronized (sSharedPrefs) {
-            if (sp != null) {
-                //Log.i(TAG, "Updating existing prefs " + name + " " + sp + ": " + map);
-                sp.replace(map);
-            } else {
-                sp = sSharedPrefs.get(name);
-                if (sp == null) {
-                    sp = new SharedPreferencesImpl(f, mode, map);
-                    sSharedPrefs.put(name, sp);
+        synchronized (sp) {
+            if (needInitialLoad && sp.isLoaded()) {
+                // lost the race to load; another thread handled it
+                return sp;
+            }
+            File backup = makeBackupFile(prefsFile);
+            if (backup.exists()) {
+                prefsFile.delete();
+                backup.renameTo(prefsFile);
+            }
+
+            // Debugging
+            if (prefsFile.exists() && !prefsFile.canRead()) {
+                Log.w(TAG, "Attempt to read preferences file " + prefsFile + " without permission");
+            }
+
+            Map map = null;
+            if (prefsFile.exists() && prefsFile.canRead()) {
+                try {
+                    FileInputStream str = new FileInputStream(prefsFile);
+                    map = XmlUtils.readMapXml(str);
+                    str.close();
+                } catch (org.xmlpull.v1.XmlPullParserException e) {
+                    Log.w(TAG, "getSharedPreferences", e);
+                } catch (FileNotFoundException e) {
+                    Log.w(TAG, "getSharedPreferences", e);
+                } catch (IOException e) {
+                    Log.w(TAG, "getSharedPreferences", e);
                 }
             }
-            return sp;
+            sp.replace(map);
         }
+        return sp;
     }
 
     private File getPreferencesDir() {
@@ -2718,6 +2718,10 @@
 
     private static final class SharedPreferencesImpl implements SharedPreferences {
 
+        // Lock ordering rules:
+        //  - acquire SharedPreferencesImpl.this before EditorImpl.this
+        //  - acquire mWritingToDiskLock before EditorImpl.this
+
         private final File mFile;
         private final File mBackupFile;
         private final int mMode;
@@ -2725,6 +2729,7 @@
         private Map<String, Object> mMap;  // guarded by 'this'
         private long mTimestamp;  // guarded by 'this'
         private int mDiskWritesInFlight = 0;  // guarded by 'this'
+        private boolean mLoaded = false;  // guarded by 'this'
 
         private final Object mWritingToDiskLock = new Object();
         private static final Object mContent = new Object();
@@ -2735,6 +2740,7 @@
             mFile = file;
             mBackupFile = makeBackupFile(file);
             mMode = mode;
+            mLoaded = initialContents != null;
             mMap = initialContents != null ? initialContents : new HashMap<String, Object>();
             FileStatus stat = new FileStatus();
             if (FileUtils.getFileStatus(file.getPath(), stat)) {
@@ -2743,7 +2749,23 @@
             mListeners = new WeakHashMap<OnSharedPreferenceChangeListener, Object>();
         }
 
-        public boolean hasFileChanged() {
+        // Has this SharedPreferences ever had values assigned to it?
+        boolean isLoaded() {
+            synchronized (this) {
+                return mLoaded;
+            }
+        }
+
+        // Has the file changed out from under us?  i.e. writes that
+        // we didn't instigate.
+        public boolean hasFileChangedUnexpectedly() {
+            synchronized (this) {
+                if (mDiskWritesInFlight > 0) {
+                    // If we know we caused it, it's not unexpected.
+                    Log.d(TAG, "disk write in flight, not unexpected.");
+                    return false;
+                }
+            }
             FileStatus stat = new FileStatus();
             if (!FileUtils.getFileStatus(mFile.getPath(), stat)) {
                 return true;
@@ -2754,8 +2776,9 @@
         }
 
         public void replace(Map newContents) {
-            if (newContents != null) {
-                synchronized (this) {
+            synchronized (this) {
+                mLoaded = true;
+                if (newContents != null) {
                     mMap = newContents;
                 }
             }
diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java
index 56cf399..16d105a 100644
--- a/core/java/android/app/Fragment.java
+++ b/core/java/android/app/Fragment.java
@@ -16,7 +16,7 @@
 
 package android.app;
 
-import android.animation.Animatable;
+import android.animation.Animator;
 import android.content.ComponentCallbacks;
 import android.content.Context;
 import android.content.Intent;
@@ -26,7 +26,6 @@
 import android.os.Parcelable;
 import android.util.AndroidRuntimeException;
 import android.util.AttributeSet;
-import android.util.Log;
 import android.util.SparseArray;
 import android.view.ContextMenu;
 import android.view.LayoutInflater;
@@ -755,7 +754,7 @@
     /**
      * Called when a fragment loads an animation.
      */
-    public Animatable onCreateAnimatable(int transit, boolean enter, int nextAnim) {
+    public Animator onCreateAnimator(int transit, boolean enter, int nextAnim) {
         return null;
     }
     
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java
index 7641f61..4d4f892 100644
--- a/core/java/android/app/FragmentManager.java
+++ b/core/java/android/app/FragmentManager.java
@@ -16,10 +16,10 @@
 
 package android.app;
 
-import android.animation.Animatable;
-import android.animation.AnimatableInflater;
-import android.animation.PropertyAnimator;
-import android.animation.Sequencer;
+import android.animation.Animator;
+import android.animation.AnimatorInflater;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
 import android.content.res.TypedArray;
 import android.os.Bundle;
 import android.os.Handler;
@@ -248,16 +248,16 @@
         return f;
     }
 
-    Animatable loadAnimatable(Fragment fragment, int transit, boolean enter,
+    Animator loadAnimator(Fragment fragment, int transit, boolean enter,
             int transitionStyle) {
-        Animatable animObj = fragment.onCreateAnimatable(transit, enter,
+        Animator animObj = fragment.onCreateAnimator(transit, enter,
                 fragment.mNextAnim);
         if (animObj != null) {
             return animObj;
         }
         
         if (fragment.mNextAnim != 0) {
-            Animatable anim = AnimatableInflater.loadAnimatable(mActivity, fragment.mNextAnim);
+            Animator anim = AnimatorInflater.loadAnimator(mActivity, fragment.mNextAnim);
             if (anim != null) {
                 return anim;
             }
@@ -288,7 +288,7 @@
             return null;
         }
         
-        return AnimatableInflater.loadAnimatable(mActivity, anim);
+        return AnimatorInflater.loadAnimator(mActivity, anim);
     }
     
     void moveToState(Fragment f, int newState, int transit, int transitionStyle) {
@@ -360,13 +360,13 @@
                             if (f.mView != null) {
                                 f.mView.setSaveFromParentEnabled(false);
                                 if (container != null) {
-                                    Animatable anim = loadAnimatable(f, transit, true,
+                                    Animator anim = loadAnimator(f, transit, true,
                                             transitionStyle);
                                     if (anim != null) {
-                                        if (anim instanceof Sequencer) {
-                                            ((Sequencer)anim).setTarget(f.mView);
-                                        } else if (anim instanceof PropertyAnimator) {
-                                            ((PropertyAnimator)anim).setTarget(f.mView);
+                                        if (anim instanceof AnimatorSet) {
+                                            ((AnimatorSet)anim).setTarget(f.mView);
+                                        } else if (anim instanceof ObjectAnimator) {
+                                            ((ObjectAnimator)anim).setTarget(f.mView);
                                         }
                                         anim.start();
                                     }
@@ -448,13 +448,13 @@
                         }
                         if (f.mView != null && f.mContainer != null) {
                             if (mCurState > Fragment.INITIALIZING) {
-                                Animatable anim = loadAnimatable(f, transit, true,
+                                Animator anim = loadAnimator(f, transit, true,
                                         transitionStyle);
                                 if (anim != null) {
-                                    if (anim instanceof Sequencer) {
-                                        ((Sequencer)anim).setTarget(f.mView);
-                                    } else if (anim instanceof PropertyAnimator) {
-                                        ((PropertyAnimator)anim).setTarget(f.mView);
+                                    if (anim instanceof AnimatorSet) {
+                                        ((AnimatorSet)anim).setTarget(f.mView);
+                                    } else if (anim instanceof ObjectAnimator) {
+                                        ((ObjectAnimator)anim).setTarget(f.mView);
                                     }
                                     anim.start();
                                 }
@@ -588,13 +588,13 @@
         if (!fragment.mHidden) {
             fragment.mHidden = true;
             if (fragment.mView != null) {
-                Animatable anim = loadAnimatable(fragment, transition, true,
+                Animator anim = loadAnimator(fragment, transition, true,
                         transitionStyle);
                 if (anim != null) {
-                    if (anim instanceof Sequencer) {
-                        ((Sequencer)anim).setTarget(fragment.mView);
-                    } else if (anim instanceof PropertyAnimator) {
-                        ((PropertyAnimator)anim).setTarget(fragment.mView);
+                    if (anim instanceof AnimatorSet) {
+                        ((AnimatorSet)anim).setTarget(fragment.mView);
+                    } else if (anim instanceof ObjectAnimator) {
+                        ((ObjectAnimator)anim).setTarget(fragment.mView);
                     }
                     anim.start();
                 }
@@ -612,13 +612,13 @@
         if (fragment.mHidden) {
             fragment.mHidden = false;
             if (fragment.mView != null) {
-                Animatable anim = loadAnimatable(fragment, transition, true,
+                Animator anim = loadAnimator(fragment, transition, true,
                         transitionStyle);
                 if (anim != null) {
-                    if (anim instanceof Sequencer) {
-                        ((Sequencer)anim).setTarget(fragment.mView);
-                    } else if (anim instanceof PropertyAnimator) {
-                        ((PropertyAnimator)anim).setTarget(fragment.mView);
+                    if (anim instanceof AnimatorSet) {
+                        ((AnimatorSet)anim).setTarget(fragment.mView);
+                    } else if (anim instanceof ObjectAnimator) {
+                        ((ObjectAnimator)anim).setTarget(fragment.mView);
                     }
                     anim.start();
                 }
diff --git a/core/java/android/app/FragmentTransaction.java b/core/java/android/app/FragmentTransaction.java
index 04598a3..9d44106 100644
--- a/core/java/android/app/FragmentTransaction.java
+++ b/core/java/android/app/FragmentTransaction.java
@@ -85,6 +85,12 @@
      * @return Returns the same FragmentTransaction instance.
      */
     public FragmentTransaction show(Fragment fragment);
+
+    /**
+     * @return <code>true</code> if this transaction contains no operations,
+     *         <code>false</code> otherwise.
+     */
+    public boolean isEmpty();
     
     /**
      * Bit mask that is set for all enter transitions.
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 359eaaa..4d0b8b0 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -1577,6 +1577,30 @@
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String ACTION_DEVICE_STORAGE_OK = "android.intent.action.DEVICE_STORAGE_OK";
     /**
+     * Broadcast Action:  A sticky broadcast that indicates a memory full
+     * condition on the device. This is intended for activities that want
+     * to be able to fill the data partition completely, leaving only
+     * enough free space to prevent system-wide SQLite failures.
+     *
+     * <p class="note">This is a protected intent that can only be sent
+     * by the system.
+     *
+     * {@hide}
+     */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_DEVICE_STORAGE_FULL = "android.intent.action.DEVICE_STORAGE_FULL";
+    /**
+     * Broadcast Action:  Indicates memory full condition on the device
+     * no longer exists.
+     *
+     * <p class="note">This is a protected intent that can only be sent
+     * by the system.
+     *
+     * {@hide}
+     */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_DEVICE_STORAGE_NOT_FULL = "android.intent.action.DEVICE_STORAGE_NOT_FULL";
+    /**
      * Broadcast Action:  Indicates low memory condition notification acknowledged by user
      * and package management should be started.
      * This is triggered by the user from the ACTION_DEVICE_STORAGE_LOW
diff --git a/core/java/android/database/sqlite/SQLiteClosable.java b/core/java/android/database/sqlite/SQLiteClosable.java
index 1830f6c..21d2ab0 100644
--- a/core/java/android/database/sqlite/SQLiteClosable.java
+++ b/core/java/android/database/sqlite/SQLiteClosable.java
@@ -30,6 +30,7 @@
 
     public void acquireReference() {
         synchronized(mLock) {
+            checkRefCount();
             if (mReferenceCount <= 0) {
                 throw new IllegalStateException(
                         "attempt to re-open an already-closed object: " + getObjInfo());
@@ -40,6 +41,7 @@
 
     public void releaseReference() {
         synchronized(mLock) {
+            checkRefCount();
             mReferenceCount--;
             if (mReferenceCount == 0) {
                 onAllReferencesReleased();
@@ -49,6 +51,7 @@
 
     public void releaseReferenceFromContainer() {
         synchronized(mLock) {
+            checkRefCount();
             mReferenceCount--;
             if (mReferenceCount == 0) {
                 onAllReferencesReleasedFromContainer();
@@ -63,8 +66,7 @@
         if (this instanceof SQLiteDatabase) {
             buff.append("database = ");
             buff.append(((SQLiteDatabase)this).getPath());
-        } else if (this instanceof SQLiteProgram || this instanceof SQLiteStatement ||
-                this instanceof SQLiteQuery) {
+        } else if (this instanceof SQLiteProgram) {
             buff.append("mSql = ");
             buff.append(((SQLiteProgram)this).mSql);
         } else if (this instanceof CursorWindow) {
@@ -74,4 +76,13 @@
         buff.append(") ");
         return buff.toString();
     }
+
+    private void checkRefCount() {
+        if (SQLiteDebug.DEBUG_ACTIVE_CURSOR_FINALIZATION) {
+            if (mReferenceCount > 1000) {
+                throw new IllegalStateException("refcount: " + mReferenceCount + ", " +
+                        getObjInfo());
+            }
+        }
+    }
 }
diff --git a/core/java/android/database/sqlite/SQLiteCompiledSql.java b/core/java/android/database/sqlite/SQLiteCompiledSql.java
index aa0a57d..0b5a4df 100644
--- a/core/java/android/database/sqlite/SQLiteCompiledSql.java
+++ b/core/java/android/database/sqlite/SQLiteCompiledSql.java
@@ -92,9 +92,6 @@
         // Note that native_finalize() checks to make sure that nStatement is
         // non-null before destroying it.
         if (nStatement != 0) {
-            if (SQLiteDebug.DEBUG_ACTIVE_CURSOR_FINALIZATION) {
-                Log.v(TAG, "closed and deallocated DbObj (id#" + nStatement +")");
-            }
             mDatabase.finalizeStatementLater(nStatement);
             nStatement = 0;
         }
@@ -109,16 +106,10 @@
             return false;
         }
         mInUse = true;
-        if (SQLiteDebug.DEBUG_ACTIVE_CURSOR_FINALIZATION) {
-            Log.v(TAG, "Acquired DbObj (id#" + nStatement + ") from DB cache");
-        }
         return true;
     }
 
     /* package */ synchronized void release() {
-        if (SQLiteDebug.DEBUG_ACTIVE_CURSOR_FINALIZATION) {
-            Log.v(TAG, "Released DbObj (id#" + nStatement + ") back to DB cache");
-        }
         mInUse = false;
     }
 
@@ -144,6 +135,22 @@
         }
     }
 
+    @Override public String toString() {
+        synchronized(this) {
+            StringBuilder buff = new StringBuilder();
+            buff.append(" nStatement=");
+            buff.append(nStatement);
+            buff.append(", db=");
+            buff.append(mDatabase.getPath());
+            buff.append(", db_connectionNum=");
+            buff.append(mDatabase.mConnectionNum);
+            buff.append(", sql=");
+            int len = mSqlStmt.length();
+            buff.append(mSqlStmt.substring(0, (len > 100) ? 100 : len));
+            return buff.toString();
+        }
+    }
+
     /**
      * Compiles SQL into a SQLite program.
      *
diff --git a/core/java/android/database/sqlite/SQLiteDatabase.java b/core/java/android/database/sqlite/SQLiteDatabase.java
index 0137ea6..6937da0 100644
--- a/core/java/android/database/sqlite/SQLiteDatabase.java
+++ b/core/java/android/database/sqlite/SQLiteDatabase.java
@@ -1066,7 +1066,7 @@
             closePendingStatements();
             releaseCustomFunctions();
             // close this database instance - regardless of its reference count value
-            dbclose();
+            closeDatabase();
             if (mConnectionPool != null) {
                 if (Log.isLoggable(TAG, Log.DEBUG)) {
                     assert mConnectionPool != null;
@@ -1075,7 +1075,7 @@
                 mConnectionPool.close();
             }
         } finally {
-            unlock();
+            unlock();            
         }
     }
 
@@ -1100,6 +1100,47 @@
     }
 
     /**
+     * package level access for testing purposes
+     */
+    /* package */ void closeDatabase() throws SQLiteException {
+        try {
+            dbclose();
+        } catch (SQLiteUnfinalizedObjectsException e)  {
+            String msg = e.getMessage();
+            String[] tokens = msg.split(",", 2);
+            int stmtId = Integer.parseInt(tokens[0]);
+            // get extra info about this statement, if it is still to be released by closeClosable()
+            Iterator<Map.Entry<SQLiteClosable, Object>> iter = mPrograms.entrySet().iterator();
+            boolean found = false;
+            while (iter.hasNext()) {
+                Map.Entry<SQLiteClosable, Object> entry = iter.next();
+                SQLiteClosable program = entry.getKey();
+                if (program != null && program instanceof SQLiteProgram) {
+                        SQLiteCompiledSql compiledSql = ((SQLiteProgram)program).mCompiledSql;
+                        if (compiledSql.nStatement == stmtId) {
+                            msg = compiledSql.toString();
+                            found = true;
+                        }
+                }
+            }
+            if (!found) {
+                // the statement is already released by closeClosable(). is it waiting to be
+                // finalized?
+                if (mClosedStatementIds.contains(stmtId)) {
+                    Log.w(TAG, "this shouldn't happen. finalizing the statement now: ");
+                    closePendingStatements();
+                    // try to close the database again
+                    closeDatabase();
+                }
+            } else {
+                // the statement is not yet closed. most probably programming error in the app.
+                Log.w(TAG, "dbclose failed due to un-close()d SQL statements: " + msg);
+                throw e;
+            }
+        }
+    }
+
+    /**
      * Native call to close the database.
      */
     private native void dbclose();
diff --git a/core/java/android/database/sqlite/SQLiteProgram.java b/core/java/android/database/sqlite/SQLiteProgram.java
index 9b7d823..bcb0c48 100644
--- a/core/java/android/database/sqlite/SQLiteProgram.java
+++ b/core/java/android/database/sqlite/SQLiteProgram.java
@@ -52,7 +52,7 @@
     /**
      * the SQLiteCompiledSql object for the given sql statement.
      */
-    private SQLiteCompiledSql mCompiledSql;
+    /* package */ SQLiteCompiledSql mCompiledSql;
 
     /**
      * SQLiteCompiledSql statement id is populated with the corresponding object from the above
@@ -130,10 +130,6 @@
             // make sure it is acquired by me.
             mCompiledSql.acquire();
             mDatabase.addToCompiledQueries(mSql, mCompiledSql);
-            if (SQLiteDebug.DEBUG_ACTIVE_CURSOR_FINALIZATION) {
-                Log.v(TAG, "Created DbObj (id#" + mCompiledSql.nStatement +
-                        ") for sql: " + mSql);
-            }
         } else {
             // it is already in compiled-sql cache.
             // try to acquire the object.
@@ -144,12 +140,6 @@
                 // CompiledSql object. create a new one.
                 // finalize it when I am done with it in "this" object.
                 mCompiledSql = new SQLiteCompiledSql(mDatabase, mSql);
-                if (SQLiteDebug.DEBUG_ACTIVE_CURSOR_FINALIZATION) {
-                    Log.v(TAG, "** possible bug ** Created NEW DbObj (id#" +
-                            mCompiledSql.nStatement +
-                            ") because the previously created DbObj (id#" + last +
-                            ") was not released for sql:" + mSql);
-                }
                 // since it is not in the cache, no need to acquire() it.
             }
         }
diff --git a/core/java/android/database/sqlite/SQLiteUnfinalizedObjectsException.java b/core/java/android/database/sqlite/SQLiteUnfinalizedObjectsException.java
new file mode 100644
index 0000000..bcf95e2
--- /dev/null
+++ b/core/java/android/database/sqlite/SQLiteUnfinalizedObjectsException.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2010 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.database.sqlite;
+
+/**
+ * Thrown if the database can't be closed because of some un-closed
+ * Cursor or SQLiteStatement objects. Could happen when a thread is trying to close
+ * the database while another thread still hasn't closed a Cursor on that database.
+ * @hide
+ */
+public class SQLiteUnfinalizedObjectsException extends SQLiteException {
+    public SQLiteUnfinalizedObjectsException() {}
+
+    public SQLiteUnfinalizedObjectsException(String error) {
+        super(error);
+    }
+}
diff --git a/core/java/android/os/AsyncTask.java b/core/java/android/os/AsyncTask.java
index aadacab..d2f3d64 100644
--- a/core/java/android/os/AsyncTask.java
+++ b/core/java/android/os/AsyncTask.java
@@ -123,6 +123,16 @@
  *     <li>The task can be executed only once (an exception will be thrown if
  *     a second execution is attempted.)</li>
  * </ul>
+ *
+ * <h2>Memory observability</h2>
+ * <p>AsyncTask guarantees that all callback calls are synchronized in such a way that the following
+ * operations are safe without explicit synchronizations.</p>
+ * <ul>
+ *     <li>Set member fields in the constructor or {@link #onPreExecute}, and refer to them
+ *     in {@link #doInBackground}.
+ *     <li>Set member fields in {@link #doInBackground}, and refer to them in
+ *     {@link #onProgressUpdate} and {@link #onPostExecute}.
+ * </ul>
  */
 public abstract class AsyncTask<Params, Progress, Result> {
     private static final String LOG_TAG = "AsyncTask";
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 9fe6e01..32fb108 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -216,6 +216,11 @@
         public abstract Map<Integer, ? extends Sensor> getSensorStats();
 
         /**
+         * Returns a mapping containing active process data.
+         */
+        public abstract SparseArray<? extends Pid> getPidStats();
+        
+        /**
          * Returns a mapping containing process statistics.
          *
          * @return a Map from Strings to Uid.Proc objects.
@@ -286,6 +291,11 @@
             public abstract Timer getSensorTime();
         }
 
+        public class Pid {
+            public long mWakeSum;
+            public long mWakeStart;
+        }
+
         /**
          * The statistics associated with a particular process.
          */
@@ -521,6 +531,11 @@
     public abstract HistoryItem getHistory();
     
     /**
+     * Return the base time offset for the battery history.
+     */
+    public abstract long getHistoryBaseTime();
+    
+    /**
      * Returns the number of times the device has been started.
      */
     public abstract int getStartCount();
@@ -1571,8 +1586,10 @@
                         sb.append(prefix); sb.append("      CPU: ");
                                 formatTime(sb, userTime); sb.append("usr + ");
                                 formatTime(sb, systemTime); sb.append("krn\n");
-                        sb.append(prefix); sb.append("      "); sb.append(starts);
-                                sb.append(" proc starts");
+                        if (starts != 0) {
+                            sb.append(prefix); sb.append("      "); sb.append(starts);
+                                    sb.append(" proc starts");
+                        }
                         pw.println(sb.toString());
                         for (int e=0; e<numExcessive; e++) {
                             Uid.Proc.ExcessiveWake ew = ps.getExcessiveWake(e);
@@ -1673,6 +1690,7 @@
         HistoryItem rec = getHistory();
         if (rec != null) {
             pw.println("Battery History:");
+            long now = getHistoryBaseTime() + SystemClock.elapsedRealtime();
             int oldState = 0;
             int oldStatus = -1;
             int oldHealth = -1;
@@ -1681,7 +1699,7 @@
             int oldVolt = -1;
             while (rec != null) {
                 pw.print("  ");
-                pw.print(rec.time);
+                TimeUtils.formatDuration(rec.time-now, pw, TimeUtils.HUNDRED_DAY_FIELD_LEN);
                 pw.print(" ");
                 if (rec.cmd == HistoryItem.CMD_START) {
                     pw.println(" START");
@@ -1784,6 +1802,35 @@
                 oldState = rec.states;
                 rec = rec.next;
             }
+            pw.println("");
+        }
+        
+        SparseArray<? extends Uid> uidStats = getUidStats();
+        final int NU = uidStats.size();
+        boolean didPid = false;
+        long nowRealtime = SystemClock.elapsedRealtime();
+        StringBuilder sb = new StringBuilder(64);
+        for (int i=0; i<NU; i++) {
+            Uid uid = uidStats.valueAt(i);
+            SparseArray<? extends Uid.Pid> pids = uid.getPidStats();
+            if (pids != null) {
+                for (int j=0; j<pids.size(); j++) {
+                    Uid.Pid pid = pids.valueAt(j);
+                    if (!didPid) {
+                        pw.println("Per-PID Stats:");
+                        didPid = true;
+                    }
+                    long time = pid.mWakeSum + (pid.mWakeStart != 0
+                            ? (nowRealtime - pid.mWakeStart) : 0);
+                    pw.print("  PID "); pw.print(pids.keyAt(j));
+                            pw.print(" wake time: ");
+                            TimeUtils.formatDuration(time, pw);
+                            pw.println("");
+                }
+            }
+        }
+        if (didPid) {
+            pw.println("");
         }
         
         pw.println("Statistics since last charge:");
diff --git a/core/java/android/provider/MediaStore.java b/core/java/android/provider/MediaStore.java
index 60ccdaf..9b2b090 100644
--- a/core/java/android/provider/MediaStore.java
+++ b/core/java/android/provider/MediaStore.java
@@ -260,31 +260,31 @@
      * Media provider interface used by MTP implementation.
      * @hide
      */
-    public static final class MtpObjects {
+    public static final class Files {
 
         public static Uri getContentUri(String volumeName) {
             return Uri.parse(CONTENT_AUTHORITY_SLASH + volumeName +
-                    "/object");
+                    "/file");
         }
 
         public static final Uri getContentUri(String volumeName,
-                long objectId) {
+                long fileId) {
             return Uri.parse(CONTENT_AUTHORITY_SLASH + volumeName
-                    + "/object/" + objectId);
+                    + "/file/" + fileId);
         }
 
         // used for MTP GetObjectReferences and SetObjectReferences
         public static final Uri getReferencesUri(String volumeName,
-                long objectId) {
+                long fileId) {
             return Uri.parse(CONTENT_AUTHORITY_SLASH + volumeName
-                    + "/object/" + objectId + "/references");
+                    + "/file/" + fileId + "/references");
         }
 
         /**
          * Fields for master table for all media files.
          * Table also contains MediaColumns._ID, DATA, SIZE and DATE_MODIFIED.
          */
-        public interface ObjectColumns extends MediaColumns {
+        public interface FileColumns extends MediaColumns {
             /**
              * The MTP format code of the file
              * <P>Type: INTEGER</P>
@@ -298,14 +298,14 @@
             public static final String PARENT = "parent";
 
             /**
-             * Identifier for the media table containing the object.
+             * Identifier for the media table containing the file.
              * Used internally by MediaProvider
              * <P>Type: INTEGER</P>
              */
             public static final String MEDIA_TABLE = "media_table";
 
             /**
-             * The ID of the object in its media table.
+             * The ID of the file in its media table.
              * <P>Type: INTEGER</P>
              */
             public static final String MEDIA_ID = "media_id";
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index dcd1d94..567ee93 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -3005,31 +3005,31 @@
         public static final String WTF_IS_FATAL = "wtf_is_fatal";
 
         /**
-         * Maximum age of entries kept by {@link android.os.IDropBox}.
+         * Maximum age of entries kept by {@link com.android.internal.os.IDropBoxManagerService}.
          * @hide
          */
         public static final String DROPBOX_AGE_SECONDS =
                 "dropbox_age_seconds";
         /**
-         * Maximum number of entry files which {@link android.os.IDropBox} will keep around.
+         * Maximum number of entry files which {@link com.android.internal.os.IDropBoxManagerService} will keep around.
          * @hide
          */
         public static final String DROPBOX_MAX_FILES =
                 "dropbox_max_files";
         /**
-         * Maximum amount of disk space used by {@link android.os.IDropBox} no matter what.
+         * Maximum amount of disk space used by {@link com.android.internal.os.IDropBoxManagerService} no matter what.
          * @hide
          */
         public static final String DROPBOX_QUOTA_KB =
                 "dropbox_quota_kb";
         /**
-         * Percent of free disk (excluding reserve) which {@link android.os.IDropBox} will use.
+         * Percent of free disk (excluding reserve) which {@link com.android.internal.os.IDropBoxManagerService} will use.
          * @hide
          */
         public static final String DROPBOX_QUOTA_PERCENT =
                 "dropbox_quota_percent";
         /**
-         * Percent of total disk which {@link android.os.IDropBox} will never dip into.
+         * Percent of total disk which {@link com.android.internal.os.IDropBoxManagerService} will never dip into.
          * @hide
          */
         public static final String DROPBOX_RESERVE_PERCENT =
@@ -3089,6 +3089,15 @@
                 "sys_storage_threshold_percentage";
 
         /**
+         * Minimum bytes of free storage on the device before the data
+         * partition is considered full. By default, 1 MB is reserved
+         * to avoid system-wide SQLite disk full exceptions.
+         * @hide
+         */
+        public static final String SYS_STORAGE_FULL_THRESHOLD_BYTES =
+                "sys_storage_full_threshold_bytes";
+
+        /**
          * The interval in milliseconds after which Wi-Fi is considered idle.
          * When idle, it is possible for the device to be switched from Wi-Fi to
          * the mobile data network.
diff --git a/core/java/android/text/format/DateUtils.java b/core/java/android/text/format/DateUtils.java
index 89b3cba..a95dad7 100644
--- a/core/java/android/text/format/DateUtils.java
+++ b/core/java/android/text/format/DateUtils.java
@@ -168,6 +168,12 @@
     public static final int FORMAT_CAP_NOON = 0x00400;
     public static final int FORMAT_NO_MIDNIGHT = 0x00800;
     public static final int FORMAT_CAP_MIDNIGHT = 0x01000;
+    /**
+     * @deprecated Use
+     * {@link #formatDateRange(Context, Formatter, long, long, int, String) formatDateRange}
+     * and pass in {@link Time#TIMEZONE_UTC Time.TIMEZONE_UTC} for the timeZone instead.
+     */
+    @Deprecated
     public static final int FORMAT_UTC = 0x02000;
     public static final int FORMAT_ABBREV_TIME = 0x04000;
     public static final int FORMAT_ABBREV_WEEKDAY = 0x08000;
@@ -964,12 +970,12 @@
      * {@link java.util.Formatter} instance and use the version of
      * {@link #formatDateRange(Context, long, long, int) formatDateRange}
      * that takes a {@link java.util.Formatter}.
-     * 
+     *
      * @param context the context is required only if the time is shown
      * @param startMillis the start time in UTC milliseconds
      * @param endMillis the end time in UTC milliseconds
      * @param flags a bit mask of options See
-     * {@link #formatDateRange(Context, long, long, int) formatDateRange}
+     * {@link #formatDateRange(Context, Formatter, long, long, int, String) formatDateRange}
      * @return a string containing the formatted date/time range.
      */
     public static String formatDateRange(Context context, long startMillis,
@@ -980,6 +986,29 @@
 
     /**
      * Formats a date or a time range according to the local conventions.
+     * <p>
+     * Note that this is a convenience method for formatting the date or
+     * time range in the local time zone. If you want to specify the time
+     * zone please use
+     * {@link #formatDateRange(Context, Formatter, long, long, int, String) formatDateRange}.
+     *
+     * @param context the context is required only if the time is shown
+     * @param formatter the Formatter used for formatting the date range.
+     * Note: be sure to call setLength(0) on StringBuilder passed to
+     * the Formatter constructor unless you want the results to accumulate.
+     * @param startMillis the start time in UTC milliseconds
+     * @param endMillis the end time in UTC milliseconds
+     * @param flags a bit mask of options See
+     * {@link #formatDateRange(Context, Formatter, long, long, int, String) formatDateRange}
+     * @return a string containing the formatted date/time range.
+     */
+    public static Formatter formatDateRange(Context context, Formatter formatter, long startMillis,
+            long endMillis, int flags) {
+        return formatDateRange(context, formatter, startMillis, endMillis, flags, null);
+    }
+
+    /**
+     * Formats a date or a time range according to the local conventions.
      * 
      * <p>
      * Example output strings (date formats in these examples are shown using
@@ -1094,8 +1123,9 @@
      * FORMAT_24HOUR takes precedence.
      * 
      * <p>
-     * If FORMAT_UTC is set, then the UTC timezone is used for the start
-     * and end milliseconds.
+     * If FORMAT_UTC is set, then the UTC time zone is used for the start
+     * and end milliseconds unless a time zone is specified. If a time zone
+     * is specified it will be used regardless of the FORMAT_UTC flag.
      * 
      * <p>
      * If FORMAT_ABBREV_TIME is set and 12-hour time format is used, then the
@@ -1127,11 +1157,13 @@
      * @param startMillis the start time in UTC milliseconds
      * @param endMillis the end time in UTC milliseconds
      * @param flags a bit mask of options
-     *   
+     * @param timeZone the time zone to compute the string in. Use null for local
+     * or if the FORMAT_UTC flag is being used.
+     *  
      * @return the formatter with the formatted date/time range appended to the string buffer.
      */
     public static Formatter formatDateRange(Context context, Formatter formatter, long startMillis,
-            long endMillis, int flags) {
+            long endMillis, int flags, String timeZone) {
         Resources res = Resources.getSystem();
         boolean showTime = (flags & FORMAT_SHOW_TIME) != 0;
         boolean showWeekDay = (flags & FORMAT_SHOW_WEEKDAY) != 0;
@@ -1148,7 +1180,14 @@
         // computation below that'd otherwise be thrown out.
         boolean isInstant = (startMillis == endMillis);
 
-        Time startDate = useUTC ? new Time(Time.TIMEZONE_UTC) : new Time();
+        Time startDate;
+        if (timeZone != null) {
+            startDate = new Time(timeZone);
+        } else if (useUTC) {
+            startDate = new Time(Time.TIMEZONE_UTC);
+        } else {
+            startDate = new Time();
+        }
         startDate.set(startMillis);
 
         Time endDate;
@@ -1157,7 +1196,13 @@
             endDate = startDate;
             dayDistance = 0;
         } else {
-            endDate = useUTC ? new Time(Time.TIMEZONE_UTC) : new Time();
+            if (timeZone != null) {
+                endDate = new Time(timeZone);
+            } else if (useUTC) {
+                endDate = new Time(Time.TIMEZONE_UTC);
+            } else {
+                endDate = new Time();
+            }
             endDate.set(endMillis);
             int startJulianDay = Time.getJulianDay(startMillis, startDate.gmtoff);
             int endJulianDay = Time.getJulianDay(endMillis, endDate.gmtoff);
diff --git a/core/java/android/text/method/ArrowKeyMovementMethod.java b/core/java/android/text/method/ArrowKeyMovementMethod.java
index 3fe14f9..0408673 100644
--- a/core/java/android/text/method/ArrowKeyMovementMethod.java
+++ b/core/java/android/text/method/ArrowKeyMovementMethod.java
@@ -34,7 +34,7 @@
      * An optional controller for the cursor.
      * Use {@link #setCursorController(CursorController)} to set this field.
      */
-    protected CursorController mCursorController;
+    private CursorController mCursorController;
 
     private boolean isCap(Spannable buffer) {
         return ((MetaKeyKeyListener.getMetaState(buffer, KeyEvent.META_SHIFT_ON) == 1) ||
@@ -302,7 +302,17 @@
     /**
      * Defines the cursor controller.
      *
-     * When set, this object can be used to handle events, that can be translated in cursor updates.
+     * When set, this object can be used to handle touch events, that can be translated into cursor
+     * updates.
+     *
+     * {@link MotionEvent#ACTION_MOVE} events will call back the 
+     * {@link CursorController#updatePosition(int, int)} controller's method, passing the current
+     * finger coordinates (offset by {@link CursorController#getOffsetX()} and
+     * {@link CursorController#getOffsetY()}) as parameters. 
+     *
+     * When the gesture is finished (on a {@link MotionEvent#ACTION_UP} or
+     * {@link MotionEvent#ACTION_CANCEL} event), the controller is reset to null.
+     *
      * @param cursorController A cursor controller implementation
      */
     public void setCursorController(CursorController cursorController) {
diff --git a/core/java/android/util/TimeUtils.java b/core/java/android/util/TimeUtils.java
index b01a71d..60ca384 100644
--- a/core/java/android/util/TimeUtils.java
+++ b/core/java/android/util/TimeUtils.java
@@ -132,20 +132,76 @@
         return ZoneInfoDB.getVersion();
     }
 
+    /** @hide Field length that can hold 999 days of time */
+    public static final int HUNDRED_DAY_FIELD_LEN = 19;
+    
     private static final int SECONDS_PER_MINUTE = 60;
     private static final int SECONDS_PER_HOUR = 60 * 60;
     private static final int SECONDS_PER_DAY = 24 * 60 * 60;
 
-    /** @hide Just for debugging; not internationalized. */
-    public static void formatDuration(long duration, StringBuilder builder) {
-        if (duration == 0) {
-            builder.append("0");
-            return;
+    private static final Object sFormatSync = new Object();
+    private static char[] sFormatStr = new char[HUNDRED_DAY_FIELD_LEN+5];
+    
+    static private int accumField(int amt, int suffix, boolean always, int zeropad) {
+        if (amt > 99 || (always && zeropad >= 3)) {
+            return 3+suffix;
         }
+        if (amt > 9 || (always && zeropad >= 2)) {
+            return 2+suffix;
+        }
+        if (always || amt > 0) {
+            return 1+suffix;
+        }
+        return 0;
+    }
+    
+    static private int printField(char[] formatStr, int amt, char suffix, int pos,
+            boolean always, int zeropad) {
+        if (always || amt > 0) {
+            if ((always && zeropad >= 3) || amt > 99) {
+                int dig = amt/100;
+                formatStr[pos] = (char)(dig + '0');
+                pos++;
+                always = true;
+                amt -= (dig*100);
+            }
+            if ((always && zeropad >= 2) || amt > 9) {
+                int dig = amt/10;
+                formatStr[pos] = (char)(dig + '0');
+                pos++;
+                always = true;
+                amt -= (dig*10);
+            }
+            formatStr[pos] = (char)(amt + '0');
+            pos++;
+            formatStr[pos] = suffix;
+            pos++;
+        }
+        return pos;
+    }
+    
+    private static int formatDurationLocked(long duration, int fieldLen) {
+        if (sFormatStr.length < fieldLen) {
+            sFormatStr = new char[fieldLen];
+        }
+        
+        char[] formatStr = sFormatStr;
+        
+        if (duration == 0) {
+            int pos = 0;
+            fieldLen -= 1;
+            while (pos < fieldLen) {
+                formatStr[pos] = ' ';
+            }
+            formatStr[pos] = '0';
+            return pos+1;
+        }
+        
+        char prefix;
         if (duration > 0) {
-            builder.append("+");
+            prefix = '+';
         } else {
-            builder.append("-");
+            prefix = '-';
             duration = -duration;
         }
 
@@ -166,93 +222,62 @@
             seconds -= minutes * SECONDS_PER_MINUTE;
         }
 
-        boolean doall = false;
-        if (days > 0) {
-            builder.append(days);
-            builder.append('d');
-            doall = true;
+        int pos = 0;
+        
+        if (fieldLen != 0) {
+            int myLen = accumField(days, 1, false, 0);
+            myLen += accumField(hours, 1, myLen > 0, 2);
+            myLen += accumField(minutes, 1, myLen > 0, 2);
+            myLen += accumField(seconds, 1, myLen > 0, 2);
+            myLen += accumField(millis, 2, true, myLen > 0 ? 3 : 0) + 1;
+            while (myLen < fieldLen) {
+                formatStr[pos] = ' ';
+                pos++;
+                myLen++;
+            }
         }
-        if (doall || hours > 0) {
-            builder.append(hours);
-            builder.append('h');
-            doall = true;
+        
+        formatStr[pos] = prefix;
+        pos++;
+        
+        int start = pos;
+        boolean zeropad = fieldLen != 0;
+        pos = printField(formatStr, days, 'd', pos, false, 0);
+        pos = printField(formatStr, hours, 'h', pos, pos != start, zeropad ? 2 : 0);
+        pos = printField(formatStr, minutes, 'm', pos, pos != start, zeropad ? 2 : 0);
+        pos = printField(formatStr, seconds, 's', pos, pos != start, zeropad ? 2 : 0);
+        pos = printField(formatStr, millis, 'm', pos, true, (zeropad && pos != start) ? 3 : 0);
+        formatStr[pos] = 's';
+        return pos + 1;
+    }
+    
+    /** @hide Just for debugging; not internationalized. */
+    public static void formatDuration(long duration, StringBuilder builder) {
+        synchronized (sFormatSync) {
+            int len = formatDurationLocked(duration, 0);
+            builder.append(sFormatStr, 0, len);
         }
-        if (doall || minutes > 0) {
-            builder.append(minutes);
-            builder.append('m');
-            doall = true;
+    }
+
+    /** @hide Just for debugging; not internationalized. */
+    public static void formatDuration(long duration, PrintWriter pw, int fieldLen) {
+        synchronized (sFormatSync) {
+            int len = formatDurationLocked(duration, fieldLen);
+            pw.print(new String(sFormatStr, 0, len));
         }
-        if (doall || seconds > 0) {
-            builder.append(seconds);
-            builder.append('s');
-            doall = true;
-        }
-        builder.append(millis);
-        builder.append("ms");
     }
 
     /** @hide Just for debugging; not internationalized. */
     public static void formatDuration(long duration, PrintWriter pw) {
-        if (duration == 0) {
-            pw.print("0");
-            return;
-        }
-        if (duration > 0) {
-            pw.print("+");
-        } else {
-            pw.print("-");
-            duration = -duration;
-        }
-
-        int millis = (int)(duration%1000);
-        int seconds = (int) Math.floor(duration / 1000);
-        int days = 0, hours = 0, minutes = 0;
-
-        if (seconds > SECONDS_PER_DAY) {
-            days = seconds / SECONDS_PER_DAY;
-            seconds -= days * SECONDS_PER_DAY;
-        }
-        if (seconds > SECONDS_PER_HOUR) {
-            hours = seconds / SECONDS_PER_HOUR;
-            seconds -= hours * SECONDS_PER_HOUR;
-        }
-        if (seconds > SECONDS_PER_MINUTE) {
-            minutes = seconds / SECONDS_PER_MINUTE;
-            seconds -= minutes * SECONDS_PER_MINUTE;
-        }
-
-        boolean doall = false;
-        if (days > 0) {
-            pw.print(days);
-            pw.print('d');
-            doall = true;
-        }
-        if (doall || hours > 0) {
-            pw.print(hours);
-            pw.print('h');
-            doall = true;
-        }
-        if (doall || minutes > 0) {
-            pw.print(minutes);
-            pw.print('m');
-            doall = true;
-        }
-        if (doall || seconds > 0) {
-            pw.print(seconds);
-            pw.print('s');
-            doall = true;
-        }
-        pw.print(millis);
-        pw.print("ms");
+        formatDuration(duration, pw, 0);
     }
-
-
+    
     /** @hide Just for debugging; not internationalized. */
     public static void formatDuration(long time, long now, PrintWriter pw) {
         if (time == 0) {
             pw.print("--");
             return;
         }
-        formatDuration(time-now, pw);
+        formatDuration(time-now, pw, 0);
     }
 }
diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java
index 74318ba..78b9b5d 100644
--- a/core/java/android/view/MotionEvent.java
+++ b/core/java/android/view/MotionEvent.java
@@ -30,6 +30,7 @@
  */
 public final class MotionEvent extends InputEvent implements Parcelable {
     private static final long MS_PER_NS = 1000000;
+    private static final boolean TRACK_RECYCLED_LOCATION = false;
     
     /**
      * Bit mask of the parts of the action code that are the action itself.
@@ -155,7 +156,17 @@
     @Deprecated
     public static final int ACTION_POINTER_ID_SHIFT = 8;
     
-    private static final boolean TRACK_RECYCLED_LOCATION = false;
+    /**
+     * This flag indicates that the window that received this motion event is partly
+     * or wholly obscured by another visible window above it.  This flag is set to true
+     * even if the event did not directly pass through the obscured area.
+     * A security sensitive application can check this flag to identify situations in which
+     * a malicious application may have covered up part of its content for the purpose
+     * of misleading the user or hijacking touches.  An appropriate response might be
+     * to drop the suspect touches or to take additional precautions to confirm the user's
+     * actual intent.
+     */
+    public static final int FLAG_WINDOW_IS_OBSCURED = 0x1;
 
     /**
      * Flag indicating the motion event intersected the top edge of the screen.
@@ -251,6 +262,7 @@
     private float mYPrecision;
     private int mEdgeFlags;
     private int mMetaState;
+    private int mFlags;
     
     private int mNumPointers;
     private int mNumSamples;
@@ -338,20 +350,22 @@
      * @param deviceId The id for the device that this event came from.  An id of
      * zero indicates that the event didn't come from a physical device; other
      * numbers are arbitrary and you shouldn't depend on the values.
-     * @param edgeFlags A bitfield indicating which edges, if any, where touched by this
+     * @param edgeFlags A bitfield indicating which edges, if any, were touched by this
      * MotionEvent.
      * @param source The source of this event.
+     * @param flags The motion event flags.
      */
     static public MotionEvent obtain(long downTime, long eventTime,
             int action, int pointers, int[] pointerIds, PointerCoords[] pointerCoords,
             int metaState, float xPrecision, float yPrecision, int deviceId,
-            int edgeFlags, int source) {
+            int edgeFlags, int source, int flags) {
         MotionEvent ev = obtain(pointers, 1);
         ev.mDeviceId = deviceId;
         ev.mSource = source;
         ev.mEdgeFlags = edgeFlags;
         ev.mDownTimeNano = downTime * MS_PER_NS;
         ev.mAction = action;
+        ev.mFlags = flags;
         ev.mMetaState = metaState;
         ev.mXOffset = 0;
         ev.mYOffset = 0;
@@ -401,7 +415,7 @@
      * @param deviceId The id for the device that this event came from.  An id of
      * zero indicates that the event didn't come from a physical device; other
      * numbers are arbitrary and you shouldn't depend on the values.
-     * @param edgeFlags A bitfield indicating which edges, if any, where touched by this
+     * @param edgeFlags A bitfield indicating which edges, if any, were touched by this
      * MotionEvent.
      */
     static public MotionEvent obtain(long downTime, long eventTime, int action,
@@ -413,6 +427,7 @@
         ev.mEdgeFlags = edgeFlags;
         ev.mDownTimeNano = downTime * MS_PER_NS;
         ev.mAction = action;
+        ev.mFlags = 0;
         ev.mMetaState = metaState;
         ev.mXOffset = 0;
         ev.mYOffset = 0;
@@ -462,7 +477,7 @@
      * @param deviceId The id for the device that this event came from.  An id of
      * zero indicates that the event didn't come from a physical device; other
      * numbers are arbitrary and you shouldn't depend on the values.
-     * @param edgeFlags A bitfield indicating which edges, if any, where touched by this
+     * @param edgeFlags A bitfield indicating which edges, if any, were touched by this
      * MotionEvent.
      * 
      * @deprecated Use {@link #obtain(long, long, int, float, float, float, float, int, float, float, int, int)}
@@ -509,6 +524,7 @@
         ev.mEdgeFlags = o.mEdgeFlags;
         ev.mDownTimeNano = o.mDownTimeNano;
         ev.mAction = o.mAction;
+        ev.mFlags = o.mFlags;
         ev.mMetaState = o.mMetaState;
         ev.mXOffset = o.mXOffset;
         ev.mYOffset = o.mYOffset;
@@ -540,6 +556,7 @@
         ev.mEdgeFlags = o.mEdgeFlags;
         ev.mDownTimeNano = o.mDownTimeNano;
         ev.mAction = o.mAction;
+        o.mFlags = o.mFlags;
         ev.mMetaState = o.mMetaState;
         ev.mXOffset = o.mXOffset;
         ev.mYOffset = o.mYOffset;
@@ -651,6 +668,15 @@
     }
 
     /**
+     * Gets the motion event flags.
+     *
+     * @see #FLAG_WINDOW_IS_OBSCURED
+     */
+    public final int getFlags() {
+        return mFlags;
+    }
+
+    /**
      * Returns the time (in ms) when the user originally pressed down to start
      * a stream of position events.
      */
@@ -1285,7 +1311,7 @@
 
 
     /**
-     * Sets the bitfield indicating which edges, if any, where touched by this
+     * Sets the bitfield indicating which edges, if any, were touched by this
      * MotionEvent.
      *
      * @see #getEdgeFlags()
@@ -1480,6 +1506,7 @@
         ev.mYPrecision = in.readFloat();
         ev.mEdgeFlags = in.readInt();
         ev.mMetaState = in.readInt();
+        ev.mFlags = in.readInt();
         
         final int[] pointerIdentifiers = ev.mPointerIdentifiers;
         for (int i = 0; i < NP; i++) {
@@ -1521,6 +1548,7 @@
         out.writeFloat(mYPrecision);
         out.writeInt(mEdgeFlags);
         out.writeInt(mMetaState);
+        out.writeInt(mFlags);
         
         final int[] pointerIdentifiers = mPointerIdentifiers;
         for (int i = 0; i < NP; i++) {
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index f8d79e5..5d258967 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -545,6 +545,28 @@
  * take care of redrawing the appropriate views until the animation completes.
  * </p>
  *
+ * <a name="Security"></a>
+ * <h3>Security</h3>
+ * <p>
+ * Sometimes it is essential that an application be able to verify that an action
+ * is being performed with the full knowledge and consent of the user, such as
+ * granting a permission request, making a purchase or clicking on an advertisement.
+ * Unfortunately, a malicious application could try to spoof the user into
+ * performing these actions, unaware, by concealing the intended purpose of the view.
+ * As a remedy, the framework offers a touch filtering mechanism that can be used to
+ * improve the security of views that provide access to sensitive functionality.
+ * </p><p>
+ * To enable touch filtering, call {@link #setFilterTouchesWhenObscured} or set the
+ * andoird:filterTouchesWhenObscured attribute to true.  When enabled, the framework
+ * will discard touches that are received whenever the view's window is obscured by
+ * another visible window.  As a result, the view will not receive touches whenever a
+ * toast, dialog or other window appears above the view's window.
+ * </p><p>
+ * For more fine-grained control over security, consider overriding the
+ * {@link #onFilterTouchEventForSecurity} method to implement your own security policy.
+ * See also {@link MotionEvent#FLAG_WINDOW_IS_OBSCURED}.
+ * </p>
+ *
  * @attr ref android.R.styleable#View_background
  * @attr ref android.R.styleable#View_clickable
  * @attr ref android.R.styleable#View_contentDescription
@@ -553,6 +575,7 @@
  * @attr ref android.R.styleable#View_id
  * @attr ref android.R.styleable#View_fadingEdge
  * @attr ref android.R.styleable#View_fadingEdgeLength
+ * @attr ref android.R.styleable#View_filterTouchesWhenObscured
  * @attr ref android.R.styleable#View_fitsSystemWindows
  * @attr ref android.R.styleable#View_isScrollContainer
  * @attr ref android.R.styleable#View_focusable
@@ -714,7 +737,14 @@
      */
     static final int SCROLLBARS_MASK = 0x00000300;
 
-    // note 0x00000400 and 0x00000800 are now available for next flags...
+    /**
+     * Indicates that the view should filter touches when its window is obscured.
+     * Refer to the class comments for more information about this security feature.
+     * {@hide}
+     */
+    static final int FILTER_TOUCHES_WHEN_OBSCURED = 0x00000400;
+
+    // note flag value 0x00000800 is now available for next flags...
 
     /**
      * <p>This view doesn't show fading edges.</p>
@@ -2171,6 +2201,12 @@
                         viewFlagMasks |= KEEP_SCREEN_ON;
                     }
                     break;
+                case R.styleable.View_filterTouchesWhenObscured:
+                    if (a.getBoolean(attr, false)) {
+                        viewFlagValues |= FILTER_TOUCHES_WHEN_OBSCURED;
+                        viewFlagMasks |= FILTER_TOUCHES_WHEN_OBSCURED;
+                    }
+                    break;
                 case R.styleable.View_nextFocusLeft:
                     mNextFocusLeftId = a.getResourceId(attr, View.NO_ID);
                     break;
@@ -3539,6 +3575,35 @@
         setFlags(enabled ? 0 : SAVE_DISABLED, SAVE_DISABLED_MASK);
     }
 
+    /**
+     * Gets whether the framework should discard touches when the view's
+     * window is obscured by another visible window.
+     * Refer to the {@link View} security documentation for more details.
+     *
+     * @return True if touch filtering is enabled.
+     *
+     * @see #setFilterTouchesWhenObscured(boolean)
+     * @attr ref android.R.styleable#View_filterTouchesWhenObscured
+     */
+    @ViewDebug.ExportedProperty
+    public boolean getFilterTouchesWhenObscured() {
+        return (mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0;
+    }
+
+    /**
+     * Sets whether the framework should discard touches when the view's
+     * window is obscured by another visible window.
+     * Refer to the {@link View} security documentation for more details.
+     *
+     * @param enabled True if touch filtering should be enabled.
+     *
+     * @see #getFilterTouchesWhenObscured
+     * @attr ref android.R.styleable#View_filterTouchesWhenObscured
+     */
+    public void setFilterTouchesWhenObscured(boolean enabled) {
+        setFlags(enabled ? 0 : FILTER_TOUCHES_WHEN_OBSCURED,
+                FILTER_TOUCHES_WHEN_OBSCURED);
+    }
 
     /**
      * Indicates whether the entire hierarchy under this view will save its
@@ -3990,6 +4055,10 @@
      * @return True if the event was handled by the view, false otherwise.
      */
     public boolean dispatchTouchEvent(MotionEvent event) {
+        if (!onFilterTouchEventForSecurity(event)) {
+            return false;
+        }
+
         if (mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED &&
                 mOnTouchListener.onTouch(this, event)) {
             return true;
@@ -3998,6 +4067,23 @@
     }
 
     /**
+     * Filter the touch event to apply security policies.
+     *
+     * @param event The motion event to be filtered.
+     * @return True if the event should be dispatched, false if the event should be dropped.
+     * 
+     * @see #getFilterTouchesWhenObscured
+     */
+    public boolean onFilterTouchEventForSecurity(MotionEvent event) {
+        if ((mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0
+                && (event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0) {
+            // Window is obscured, drop this touch.
+            return false;
+        }
+        return true;
+    }
+
+    /**
      * Pass a trackball motion event down to the focused view.
      *
      * @param event The motion event to be dispatched.
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 363ccd6..c8b26ef 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -868,12 +868,16 @@
      */
     @Override
     public boolean dispatchTouchEvent(MotionEvent ev) {
+        if (!onFilterTouchEventForSecurity(ev)) {
+            return false;
+        }
+
         if ((mGroupFlags & FLAG_SPLIT_MOTION_EVENTS) == FLAG_SPLIT_MOTION_EVENTS) {
             if (mSplitMotionTargets == null) {
                 mSplitMotionTargets = new SplitMotionTargets();
             }
             return dispatchSplitTouchEvent(ev);
-        }
+	}
 
         final int action = ev.getAction();
         final float xf = ev.getX();
@@ -4471,7 +4475,7 @@
             return MotionEvent.obtain(downTime, ev.getEventTime(),
                     action, pointerCount, mPointerIds, mPointerCoords, ev.getMetaState(),
                     ev.getXPrecision(), ev.getYPrecision(), ev.getDeviceId(), ev.getEdgeFlags(),
-                    ev.getSource());
+                    ev.getSource(), ev.getFlags());
         }
 
         static class TargetInfo {
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index 659f9cd..76701a9 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -74,6 +74,8 @@
     public final static int FLAG_MENU = 0x00000040;
     public final static int FLAG_LAUNCHER = 0x00000080;
 
+    public final static int FLAG_INJECTED = 0x01000000;
+
     public final static int FLAG_WOKE_HERE = 0x10000000;
     public final static int FLAG_BRIGHT_HERE = 0x20000000;
 
diff --git a/core/java/android/view/animation/AnimationUtils.java b/core/java/android/view/animation/AnimationUtils.java
index c090f8e..32ff647 100644
--- a/core/java/android/view/animation/AnimationUtils.java
+++ b/core/java/android/view/animation/AnimationUtils.java
@@ -35,7 +35,7 @@
 public class AnimationUtils {
 
     /**
-     * These flags are used when parsing Sequencer objects
+     * These flags are used when parsing AnimatorSet objects
      */
     private static final int TOGETHER = 0;
     private static final int SEQUENTIALLY = 1;
diff --git a/core/java/android/widget/AdapterViewAnimator.java b/core/java/android/widget/AdapterViewAnimator.java
index 830e899..e8d96c5 100644
--- a/core/java/android/widget/AdapterViewAnimator.java
+++ b/core/java/android/widget/AdapterViewAnimator.java
@@ -18,12 +18,10 @@
 
 import java.util.ArrayList;
 
-import android.animation.PropertyAnimator;
+import android.animation.ObjectAnimator;
 import android.content.Context;
 import android.content.Intent;
 import android.content.res.TypedArray;
-import android.graphics.Rect;
-import android.graphics.RectF;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Parcel;
@@ -220,13 +218,13 @@
      * @param view The view that is being animated
      */
     void animateViewForTransition(int fromIndex, int toIndex, View view) {
-        PropertyAnimator pa;
+        ObjectAnimator pa;
         if (fromIndex == -1) {
             view.setAlpha(0.0f);
-            pa = new PropertyAnimator(400, view, "alpha", 0.0f, 1.0f);
+            pa = new ObjectAnimator(400, view, "alpha", 0.0f, 1.0f);
             pa.start();
         } else if (toIndex == -1) {
-            pa = new PropertyAnimator(400, view, "alpha", 1.0f, 0.0f);
+            pa = new ObjectAnimator(400, view, "alpha", 1.0f, 0.0f);
             pa.start();
         }
     }
diff --git a/core/java/android/widget/QuickContactBadge.java b/core/java/android/widget/QuickContactBadge.java
index 50fbb6b..5598c65 100644
--- a/core/java/android/widget/QuickContactBadge.java
+++ b/core/java/android/widget/QuickContactBadge.java
@@ -247,6 +247,7 @@
                         trigger = true;
                         createUri = Uri.fromParts("tel", (String)cookie, null);
 
+                        //$FALL-THROUGH$
                     case TOKEN_PHONE_LOOKUP: {
                         if (cursor != null && cursor.moveToFirst()) {
                             long contactId = cursor.getLong(PHONE_ID_COLUMN_INDEX);
@@ -260,12 +261,14 @@
                         trigger = true;
                         createUri = Uri.fromParts("mailto", (String)cookie, null);
 
+                        //$FALL-THROUGH$
                     case TOKEN_EMAIL_LOOKUP: {
                         if (cursor != null && cursor.moveToFirst()) {
                             long contactId = cursor.getLong(EMAIL_ID_COLUMN_INDEX);
                             String lookupKey = cursor.getString(EMAIL_LOOKUP_STRING_COLUMN_INDEX);
                             lookupUri = Contacts.getLookupUri(contactId, lookupKey);
                         }
+                        break;
                     }
 
                     case TOKEN_CONTACT_LOOKUP_AND_TRIGGER: {
diff --git a/core/java/android/widget/StackView.java b/core/java/android/widget/StackView.java
index 9025b83..0a97904 100644
--- a/core/java/android/widget/StackView.java
+++ b/core/java/android/widget/StackView.java
@@ -16,8 +16,8 @@
 
 package android.widget;
 
-import android.animation.PropertyAnimator;
 import android.animation.PropertyValuesHolder;
+import android.animation.ObjectAnimator;
 import android.content.Context;
 import android.graphics.Bitmap;
 import android.graphics.BlurMaskFilter;
@@ -166,7 +166,7 @@
             }
             view.setVisibility(VISIBLE);
 
-            PropertyAnimator<Float> fadeIn = new PropertyAnimator<Float>(DEFAULT_ANIMATION_DURATION,
+            ObjectAnimator<Float> fadeIn = new ObjectAnimator<Float>(DEFAULT_ANIMATION_DURATION,
                     view, "alpha", view.getAlpha(), 1.0f);
             fadeIn.start();
         } else if (fromIndex == mNumActiveViews - 1 && toIndex == mNumActiveViews - 2) {
@@ -181,7 +181,7 @@
                     new PropertyValuesHolder<Float>("YProgress", 0.0f);
             PropertyValuesHolder<Float> slideInX =
                     new PropertyValuesHolder<Float>("XProgress", 0.0f);
-            PropertyAnimator pa = new PropertyAnimator(duration, animationSlider,
+            ObjectAnimator pa = new ObjectAnimator(duration, animationSlider,
                     slideInX, slideInY);
             pa.setInterpolator(new LinearInterpolator());
             pa.start();
@@ -196,7 +196,7 @@
                     new PropertyValuesHolder<Float>("YProgress", 1.0f);
             PropertyValuesHolder<Float> slideOutX =
                     new PropertyValuesHolder<Float>("XProgress", 0.0f);
-            PropertyAnimator pa = new PropertyAnimator(duration, animationSlider,
+            ObjectAnimator pa = new ObjectAnimator(duration, animationSlider,
                    slideOutX, slideOutY);
             pa.setInterpolator(new LinearInterpolator());
             pa.start();
@@ -208,7 +208,7 @@
             lp.setVerticalOffset(-mViewHeight);
         } else if (toIndex == -1) {
             // Fade item out
-            PropertyAnimator<Float> fadeOut = new PropertyAnimator<Float>
+            ObjectAnimator<Float> fadeOut = new ObjectAnimator<Float>
                     (DEFAULT_ANIMATION_DURATION, view, "alpha", view.getAlpha(), 0.0f);
             fadeOut.start();
         }
@@ -234,7 +234,7 @@
 
             PropertyValuesHolder<Float> translationY =
                     new PropertyValuesHolder<Float>("translationY", transY);
-            PropertyAnimator pa = new PropertyAnimator(100, view, scaleX, scaleY, translationY);
+            ObjectAnimator pa = new ObjectAnimator(100, view, scaleX, scaleY, translationY);
             pa.start();
         }
     }
@@ -510,7 +510,7 @@
                     new PropertyValuesHolder<Float>("YProgress", finalYProgress);
             PropertyValuesHolder<Float> snapBackX =
                     new PropertyValuesHolder<Float>("XProgress", 0.0f);
-            PropertyAnimator pa = new PropertyAnimator(duration, animationSlider,
+            ObjectAnimator pa = new ObjectAnimator(duration, animationSlider,
                     snapBackX, snapBackY);
             pa.setInterpolator(new LinearInterpolator());
             pa.start();
@@ -529,7 +529,7 @@
                     new PropertyValuesHolder<Float>("YProgress", finalYProgress);
             PropertyValuesHolder<Float> snapBackX =
                     new PropertyValuesHolder<Float>("XProgress", 0.0f);
-            PropertyAnimator pa = new PropertyAnimator(duration, animationSlider,
+            ObjectAnimator pa = new ObjectAnimator(duration, animationSlider,
                     snapBackX, snapBackY);
             pa.start();
         }
@@ -870,7 +870,7 @@
 
         private Rect invalidateRect = new Rect();
         private RectF invalidateRectf = new RectF();
-        // This is public so that PropertyAnimator can access it
+        // This is public so that ObjectAnimator can access it
         public void setVerticalOffset(int newVerticalOffset) {
             int offsetDelta = newVerticalOffset - verticalOffset;
             verticalOffset = newVerticalOffset;
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 9961438..dabe7ba 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -21,8 +21,8 @@
 
 import org.xmlpull.v1.XmlPullParserException;
 
-import android.content.ClipboardManager;
 import android.content.ClipData;
+import android.content.ClipboardManager;
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.content.res.ColorStateList;
@@ -36,6 +36,7 @@
 import android.graphics.RectF;
 import android.graphics.Typeface;
 import android.graphics.drawable.Drawable;
+import android.inputmethodservice.ExtractEditText;
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.Handler;
@@ -3704,18 +3705,21 @@
 
         boolean changed = false;
 
+        SelectionModifierCursorController selectionController = null;
+        if (mSelectionModifierCursorController != null) {
+            selectionController = (SelectionModifierCursorController)
+                mSelectionModifierCursorController;
+        }
+
+
         if (mMovement != null) {
             /* This code also provides auto-scrolling when a cursor is moved using a
              * CursorController (insertion point or selection limits).
              * For selection, ensure start or end is visible depending on controller's state.
              */
             int curs = getSelectionEnd();
-            if (mSelectionModifierCursorController != null) {
-                SelectionModifierCursorController selectionController =
-                    (SelectionModifierCursorController) mSelectionModifierCursorController;
-                if (selectionController.isSelectionStartDragged()) {
-                    curs = getSelectionStart();
-                }
+            if (selectionController != null && selectionController.isSelectionStartDragged()) {
+                curs = getSelectionStart();
             }
 
             /*
@@ -3735,10 +3739,16 @@
             changed = bringTextIntoView();
         }
 
-        if (mShouldStartSelectionActionMode) {
+        // This has to be checked here since:
+        // - onFocusChanged cannot start it when focus is given to a view with selected text (after
+        //   a screen rotation) since layout is not yet initialized at that point.
+        // - ExtractEditText does not call onFocus when it is displayed. Fixing this issue would
+        //   allow to test for hasSelection in onFocusChanged, which would trigger a
+        //   startTextSelectionMode here. TODO
+        if (selectionController != null && hasSelection()) {
             startSelectionActionMode();
-            mShouldStartSelectionActionMode = false;
         }
+
         mPreDrawState = PREDRAW_DONE;
         return !changed;
     }
@@ -4350,6 +4360,15 @@
                 if (shouldAdvanceFocusOnEnter()) {
                     return 0;
                 }
+                break;
+
+                // Has to be done on key down (and not on key up) to correctly be intercepted.
+            case KeyEvent.KEYCODE_BACK:
+                if (mSelectionActionMode != null) {
+                    stopSelectionActionMode();
+                    return -1;
+                }
+                break;
         }
 
         if (mInput != null) {
@@ -4503,6 +4522,7 @@
 
                     return super.onKeyUp(keyCode, event);
                 }
+                break;
         }
 
         if (mInput != null)
@@ -6434,11 +6454,6 @@
                 sendAccessibilityEventTypeViewTextChanged(mBeforeText, start, before, after);
                 mBeforeText = null;
             }
-
-            // TODO. The cursor controller should hide as soon as text is typed.
-            // But this method is also used for cosmetic changes (underline current word when
-            // spell corrections are displayed. There is currently no way to make the difference
-            // between these cosmetic changes and actual text modifications.
         }
 
         public void afterTextChanged(Editable buffer) {
@@ -6530,13 +6545,9 @@
             int selEnd = getSelectionEnd();
 
             if (!mFrozenWithFocus || (selStart < 0 || selEnd < 0)) {
-                boolean selMoved = mSelectionMoved;
-
-                if (mSelectionModifierCursorController != null) {
-                    final int touchOffset = 
-                        ((SelectionModifierCursorController) mSelectionModifierCursorController).
-                        getMinTouchOffset();
-                    Selection.setSelection((Spannable) mText, touchOffset);
+                // Has to be done before onTakeFocus, which can be overloaded.
+                if (mLastTouchOffset >= 0) {
+                    Selection.setSelection((Spannable) mText, mLastTouchOffset);
                 }
 
                 if (mMovement != null) {
@@ -6547,7 +6558,12 @@
                     Selection.setSelection((Spannable) mText, 0, mText.length());
                 }
 
-                if (selMoved && selStart >= 0 && selEnd >= 0) {
+                // The DecorView does not have focus when the 'Done' ExtractEditText button is
+                // pressed. Since it is the ViewRoot's mView, it requests focus before
+                // ExtractEditText clears focus, which gives focus to the ExtractEditText.
+                // This special case ensure that we keep current selection in that case.
+                // It would be better to know why the DecorView does not have focus at that time.
+                if (((this instanceof ExtractEditText) || mSelectionMoved) && selStart >= 0 && selEnd >= 0) {
                     /*
                      * Someone intentionally set the selection, so let them
                      * do whatever it is that they wanted to do instead of
@@ -6557,7 +6573,6 @@
                      * just setting the selection in theirs and we still
                      * need to go through that path.
                      */
-
                     Selection.setSelection((Spannable) mText, selStart, selEnd);
                 }
                 mTouchFocusSelected = true;
@@ -6576,13 +6591,6 @@
             if (mError != null) {
                 showError();
             }
-
-            // We cannot start the selection mode immediately. The layout may be null here and is
-            // needed by the cursor controller. Layout creation is deferred up to drawing. The
-            // selection action mode will be started in onPreDraw().
-            if (selStart != selEnd) {
-                mShouldStartSelectionActionMode = true;
-            }
         } else {
             if (mError != null) {
                 hideError();
@@ -6591,14 +6599,22 @@
             onEndBatchEdit();
 
             hideInsertionPointCursorController();
-            terminateSelectionActionMode();
+            if (this instanceof ExtractEditText) {
+                // terminateTextSelectionMode removes selection, which we want to keep when
+                // ExtractEditText goes out of focus.
+                final int selStart = getSelectionStart();
+                final int selEnd = getSelectionEnd();
+                terminateSelectionActionMode();
+                Selection.setSelection((Spannable) mText, selStart, selEnd);
+            } else {
+                terminateSelectionActionMode();
+            }
         }
 
         startStopMarquee(focused);
 
         if (mTransformation != null) {
-            mTransformation.onFocusChanged(this, mText, focused, direction,
-                                           previouslyFocusedRect);
+            mTransformation.onFocusChanged(this, mText, focused, direction, previouslyFocusedRect);
         }
 
         super.onFocusChanged(focused, direction, previouslyFocusedRect);
@@ -6657,59 +6673,57 @@
         }
     }
 
-    class CommitSelectionReceiver extends ResultReceiver {
-        private final int mPrevStart, mPrevEnd;
-        private final int mNewStart, mNewEnd;
+    private void onTapUpEvent(int prevStart, int prevEnd) {
+        final int start = getSelectionStart();
+        final int end = getSelectionEnd();
 
-        public CommitSelectionReceiver(int mPrevStart, int mPrevEnd, int mNewStart, int mNewEnd) {
-            super(getHandler());
-            this.mPrevStart = mPrevStart;
-            this.mPrevEnd = mPrevEnd;
-            this.mNewStart = mNewStart;
-            this.mNewEnd = mNewEnd;
-        }
-
-        @Override
-        protected void onReceiveResult(int resultCode, Bundle resultData) {
-            int start = mNewStart;
-            int end = mNewEnd;
-
-            // Move the cursor to the new position, unless this tap was actually
-            // use to show the IMM. Leave cursor unchanged in that case.
-            if (resultCode == InputMethodManager.RESULT_SHOWN) {
-                start = mPrevStart;
-                end = mPrevEnd;
+        if (start == end) {
+            if (start >= prevStart && start < prevEnd) {
+                // Tapping inside the selection displays the cut/copy/paste context menu.
+                showContextMenu();
+                return;
             } else {
-                if ((mPrevStart != mPrevEnd) && (start == end)) {
-                    if ((start >= mPrevStart) && (start <= mPrevEnd)) {
-                        // Tapping inside the selection does nothing
-                        Selection.setSelection((Spannable) mText, mPrevStart, mPrevEnd);
-                        return;
-                    } else {
-                        // Tapping outside stops selection mode, if any
-                        stopSelectionActionMode();
-                    }
-                }
+                // Tapping outside stops selection mode, if any
+                stopSelectionActionMode();
 
                 if (mInsertionPointCursorController != null) {
                     mInsertionPointCursorController.show();
                 }
             }
-
-            final int len = mText.length();
-            if (start > len) {
-                start = len;
-            }
-            if (end > len) {
-                end = len;
-            }
-            Selection.setSelection((Spannable)mText, start, end);
         }
     }
-    
+
+    class CommitSelectionReceiver extends ResultReceiver {
+        private final int mPrevStart, mPrevEnd;
+
+        public CommitSelectionReceiver(int prevStart, int prevEnd) {
+            super(getHandler());
+            mPrevStart = prevStart;
+            mPrevEnd = prevEnd;
+        }
+
+        @Override
+        protected void onReceiveResult(int resultCode, Bundle resultData) {
+            // If this tap was actually used to show the IMM, leave cursor or selection unchanged
+            // by restoring its previous position.
+            if (resultCode == InputMethodManager.RESULT_SHOWN) {
+                final int len = mText.length();
+                int start = Math.min(len, mPrevStart);
+                int end = Math.min(len, mPrevEnd);
+                Selection.setSelection((Spannable)mText, start, end);
+
+                if (hasSelection()) {
+                    startSelectionActionMode();
+                } else if (mInsertionPointCursorController != null) {
+                    mInsertionPointCursorController.show();
+                }
+            }
+        }
+    }
+
     @Override
     public boolean onTouchEvent(MotionEvent event) {
-        final int action = event.getAction();
+        final int action = event.getActionMasked();
         if (action == MotionEvent.ACTION_DOWN) {
             // Reset this state; it will be re-set if super.onTouchEvent
             // causes focus to move to the view.
@@ -6729,11 +6743,7 @@
             return superResult;
         }
 
-        if ((mMovement != null || onCheckIsTextEditor()) &&
-                mText instanceof Spannable && mLayout != null) {
-            
-            int oldSelStart = getSelectionStart();
-            int oldSelEnd = getSelectionEnd();
+        if ((mMovement != null || onCheckIsTextEditor()) && mText instanceof Spannable && mLayout != null) {
 
             if (mInsertionPointCursorController != null) {
                 mInsertionPointCursorController.onTouchEvent(event);
@@ -6744,6 +6754,10 @@
 
             boolean handled = false;
 
+            // Save previous selection, in case this event is used to show the IME.
+            int oldSelStart = getSelectionStart();
+            int oldSelEnd = getSelectionEnd();
+
             if (mMovement != null) {
                 handled |= mMovement.onTouchEvent(this, (Spannable) mText, event);
             }
@@ -6753,17 +6767,17 @@
                     InputMethodManager imm = (InputMethodManager)
                           getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
 
-                    final int newSelStart = getSelectionStart();
-                    final int newSelEnd = getSelectionEnd();
-
                     CommitSelectionReceiver csr = null;
-                    if (newSelStart != oldSelStart || newSelEnd != oldSelEnd ||
+                    if (getSelectionStart() != oldSelStart || getSelectionEnd() != oldSelEnd ||
                             didTouchFocusSelect()) {
-                        csr = new CommitSelectionReceiver(oldSelStart, oldSelEnd,
-                                newSelStart, newSelEnd);
+                        csr = new CommitSelectionReceiver(oldSelStart, oldSelEnd);
                     }
 
                     handled |= imm.showSoftInput(this, 0, csr) && (csr != null);
+
+                    // Cannot be done by CommitSelectionReceiver, which might not always be called,
+                    // for instance when dealing with an ExtractEditText.
+                    onTapUpEvent(oldSelStart, oldSelEnd);
                 }
             }
 
@@ -7313,10 +7327,11 @@
     public boolean onTextContextMenuItem(int id) {
         int min = 0;
         int max = mText.length();
-        
+
         if (isFocused()) {
-            int selStart = getSelectionStart();
-            int selEnd = getSelectionEnd();
+            final int selStart = getSelectionStart();
+            final int selEnd = getSelectionEnd();
+
             min = Math.max(0, Math.min(selStart, selEnd));
             max = Math.max(0, Math.max(selStart, selEnd));
         }
@@ -7326,7 +7341,6 @@
 
         switch (id) {
             case ID_COPY_URL:
-                MetaKeyKeyListener.stopSelecting(this, (Spannable) mText);
 
                 URLSpan[] urls = ((Spanned) mText).getSpans(min, max, URLSpan.class);
                 if (urls.length >= 1) {
@@ -7649,7 +7663,7 @@
         Handle(Drawable drawable) {
             mDrawable = drawable;
         }
-        
+
         void positionAtCursor(final int offset, boolean bottom) {
             final int drawableWidth = mDrawable.getIntrinsicWidth();
             final int drawableHeight = mDrawable.getIntrinsicHeight();
@@ -7660,8 +7674,9 @@
             mHotSpotVerticalPosition = lineTop;
 
             final Rect bounds = sCursorControllerTempRect;
-            bounds.left = (int) (mLayout.getPrimaryHorizontal(offset) - drawableWidth / 2.0);
-            bounds.top = (bottom ? lineBottom : lineTop) - drawableHeight / 2;
+            bounds.left = (int) (mLayout.getPrimaryHorizontal(offset) - drawableWidth / 2.0)
+                + mScrollX;
+            bounds.top = (bottom ? lineBottom : lineTop) - drawableHeight / 2 + mScrollY;
 
             mTopExtension = bottom ? 0 : drawableHeight / 2;
             mBottomExtension = drawableHeight;
@@ -7669,7 +7684,7 @@
             // Extend touch region up when editing the last line of text (or a single line) so that
             // it is easier to grab.
             if (line == mLayout.getLineCount() - 1) {
-                  mTopExtension = (lineBottom - lineTop) - drawableHeight / 2;
+                mTopExtension = (lineBottom - lineTop) - drawableHeight / 2;
             }
 
             bounds.right = bounds.left + drawableWidth;
@@ -7692,6 +7707,7 @@
                            (int) (y - mBottomExtension),
                            (int) (x + drawableWidth / 2.0),
                            (int) (y + mTopExtension));
+            fingerRect.offset(mScrollX, mScrollY);
             return Rect.intersects(mDrawable.getBounds(), fingerRect);
         }
 
@@ -7985,7 +8001,7 @@
                         final int y = (int) event.getY();
 
                         // Remember finger down position, to be able to start selection from there
-                        mMinTouchOffset = mMaxTouchOffset = getOffset(x, y);
+                        mMinTouchOffset = mMaxTouchOffset = mLastTouchOffset = getOffset(x, y);
 
                         if (mIsVisible) {
                             if (mMovement instanceof ArrowKeyMovementMethod) {
@@ -8001,7 +8017,8 @@
                                     // In case both controllers are under finger (very small
                                     // selection region), arbitrarily pick end controller.
                                     mStartIsDragged = !isOnEnd;
-                                    final Handle draggedHandle = mStartIsDragged ? mStartHandle : mEndHandle;
+                                    final Handle draggedHandle =
+                                        mStartIsDragged ? mStartHandle : mEndHandle;
                                     final Rect bounds = draggedHandle.mDrawable.getBounds();
                                     mOffsetX = (bounds.left + bounds.right) / 2.0f - x;
                                     mOffsetY = draggedHandle.mHotSpotVerticalPosition - y;
@@ -8166,8 +8183,8 @@
     // Cursor Controllers. Null when disabled.
     private CursorController        mInsertionPointCursorController;
     private CursorController        mSelectionModifierCursorController;
-    private boolean                 mShouldStartSelectionActionMode = false;
     private ActionMode              mSelectionActionMode;
+    private int                     mLastTouchOffset = -1;
     // Created once and shared by different CursorController helper methods.
     // Only one cursor controller is active at any time which prevent race conditions.
     private static Rect             sCursorControllerTempRect = new Rect();
diff --git a/core/java/com/android/internal/app/ActionBarImpl.java b/core/java/com/android/internal/app/ActionBarImpl.java
index 1048352..cf029d2 100644
--- a/core/java/com/android/internal/app/ActionBarImpl.java
+++ b/core/java/com/android/internal/app/ActionBarImpl.java
@@ -122,17 +122,6 @@
     }
 
     @Override
-    public void setStandardNavigationMode(int titleResId, int subtitleResId) {
-        setStandardNavigationMode(mContext.getString(titleResId),
-                mContext.getString(subtitleResId));
-    }
-
-    @Override
-    public void setStandardNavigationMode(int titleResId) {
-        setStandardNavigationMode(mContext.getString(titleResId));
-    }
-
-    @Override
     public void setTitle(int resId) {
         setTitle(mContext.getString(resId));
     }
@@ -169,19 +158,6 @@
         mActionView.setCallback(null);
     }
 
-    public void setStandardNavigationMode(CharSequence title) {
-        cleanupTabs();
-        setStandardNavigationMode(title, null);
-    }
-
-    public void setStandardNavigationMode(CharSequence title, CharSequence subtitle) {
-        cleanupTabs();
-        mActionView.setNavigationMode(NAVIGATION_MODE_STANDARD);
-        mActionView.setTitle(title);
-        mActionView.setSubtitle(subtitle);
-        mActionView.setCallback(null);
-    }
-
     public void setSelectedNavigationItem(int position) {
         switch (mActionView.getNavigationMode()) {
         case NAVIGATION_MODE_TABS:
@@ -211,17 +187,7 @@
         if (mSelectedTab != null) {
             selectTab(null);
         }
-        if (!mTabs.isEmpty()) {
-            if (mTabSwitchMode == TAB_SWITCH_SHOW_HIDE) {
-                final FragmentTransaction trans = mActivity.openFragmentTransaction();
-                final int tabCount = mTabs.size();
-                for (int i = 0; i < tabCount; i++) {
-                    trans.remove(mTabs.get(i).getFragment());
-                }
-                trans.commit();
-            }
-            mTabs.clear();
-        }
+        mTabs.clear();
     }
 
     public void setTitle(CharSequence title) {
@@ -295,31 +261,23 @@
     private void configureTab(Tab tab, int position) {
         final TabImpl tabi = (TabImpl) tab;
         final boolean isFirstTab = mTabs.isEmpty();
-        final FragmentTransaction trans = mActivity.openFragmentTransaction();
-        final Fragment frag = tabi.getFragment();
+        final ActionBar.TabListener callback = tabi.getCallback();
+
+        if (callback == null) {
+            throw new IllegalStateException("Action Bar Tab must have a Callback");
+        }
 
         tabi.setPosition(position);
         mTabs.add(position, tabi);
 
-        if (mTabSwitchMode == TAB_SWITCH_SHOW_HIDE) {
-            if (!frag.isAdded()) {
-                trans.add(mTabContainerViewId, frag);
-            }
-        }
-
         if (isFirstTab) {
-            if (mTabSwitchMode == TAB_SWITCH_SHOW_HIDE) {
-                trans.show(frag);
-            } else if (mTabSwitchMode == TAB_SWITCH_ADD_REMOVE) {
-                trans.add(mTabContainerViewId, frag);
-            }
+            final FragmentTransaction trans = mActivity.getFragmentManager().openTransaction();
             mSelectedTab = tabi;
-        } else {
-            if (mTabSwitchMode == TAB_SWITCH_SHOW_HIDE) {
-                trans.hide(frag);
+            callback.onTabSelected(tab, trans);
+            if (!trans.isEmpty()) {
+                trans.commit();
             }
         }
-        trans.commit();
     }
 
     @Override
@@ -329,8 +287,8 @@
     }
 
     @Override
-    public void insertTab(Tab tab, int position) {
-        mActionView.insertTab(tab, position);
+    public void addTab(Tab tab, int position) {
+        mActionView.addTab(tab, position);
         configureTab(tab, position);
     }
 
@@ -367,35 +325,29 @@
     }
 
     @Override
-    public void setTabNavigationMode(int containerViewId) {
-        mTabContainerViewId = containerViewId;
-        setTabNavigationMode();
-    }
-
-    @Override
     public void selectTab(Tab tab) {
         if (mSelectedTab == tab) {
             return;
         }
 
         mActionView.setTabSelected(tab != null ? tab.getPosition() : Tab.INVALID_POSITION);
-        final FragmentTransaction trans = mActivity.openFragmentTransaction();
+        final FragmentTransaction trans = mActivity.getFragmentManager().openTransaction();
         if (mSelectedTab != null) {
-            if (mTabSwitchMode == TAB_SWITCH_SHOW_HIDE) {
-                trans.hide(mSelectedTab.getFragment());
-            } else if (mTabSwitchMode == TAB_SWITCH_ADD_REMOVE) {
-                trans.remove(mSelectedTab.getFragment());
-            }
-        }
-        if (tab != null) {
-            if (mTabSwitchMode == TAB_SWITCH_SHOW_HIDE) {
-                trans.show(tab.getFragment());
-            } else if (mTabSwitchMode == TAB_SWITCH_ADD_REMOVE) {
-                trans.add(mTabContainerViewId, tab.getFragment());
-            }
+            mSelectedTab.getCallback().onTabUnselected(mSelectedTab, trans);
         }
         mSelectedTab = (TabImpl) tab;
-        trans.commit();
+        if (mSelectedTab != null) {
+            mSelectedTab.getCallback().onTabSelected(mSelectedTab, trans);
+        }
+
+        if (!trans.isEmpty()) {
+            trans.commit();
+        }
+    }
+
+    @Override
+    public Tab getSelectedTab() {
+        return mSelectedTab;
     }
 
     @Override
@@ -542,14 +494,40 @@
      * @hide
      */
     public class TabImpl extends ActionBar.Tab {
-        private Fragment mFragment;
+        private ActionBar.TabListener mCallback;
+        private Object mTag;
         private Drawable mIcon;
         private CharSequence mText;
         private int mPosition;
+        private View mCustomView;
 
         @Override
-        public Fragment getFragment() {
-            return mFragment;
+        public Object getTag() {
+            return mTag;
+        }
+
+        @Override
+        public void setTag(Object tag) {
+            mTag = tag;
+        }
+
+        public ActionBar.TabListener getCallback() {
+            return mCallback;
+        }
+
+        @Override
+        public void setTabListener(ActionBar.TabListener callback) {
+            mCallback = callback;
+        }
+
+        @Override
+        public View getCustomView() {
+            return mCustomView;
+        }
+
+        @Override
+        public void setCustomView(View view) {
+            mCustomView = view;
         }
 
         @Override
@@ -572,11 +550,6 @@
         }
 
         @Override
-        public void setFragment(Fragment fragment) {
-            mFragment = fragment;
-        }
-
-        @Override
         public void setIcon(Drawable icon) {
             mIcon = icon;
         }
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 0a1c8ff..9ed3658 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -22,6 +22,8 @@
 import android.net.TrafficStats;
 import android.os.BatteryManager;
 import android.os.BatteryStats;
+import android.os.Handler;
+import android.os.Message;
 import android.os.Parcel;
 import android.os.ParcelFormatException;
 import android.os.Parcelable;
@@ -79,6 +81,38 @@
 
     private final JournaledFile mFile;
 
+    static final int MSG_UPDATE_WAKELOCKS = 1;
+    static final int MSG_REPORT_POWER_CHANGE = 2;
+    static final long DELAY_UPDATE_WAKELOCKS = 15*1000;
+
+    public interface BatteryCallback {
+        public void batteryNeedsCpuUpdate();
+        public void batteryPowerChanged(boolean onBattery);
+    }
+
+    final class MyHandler extends Handler {
+        @Override
+        public void handleMessage(Message msg) {
+            BatteryCallback cb = mCallback;
+            switch (msg.what) {
+                case MSG_UPDATE_WAKELOCKS:
+                    if (cb != null) {
+                        cb.batteryNeedsCpuUpdate();
+                    }
+                    break;
+                case MSG_REPORT_POWER_CHANGE:
+                    if (cb != null) {
+                        cb.batteryPowerChanged(msg.arg1 != 0);
+                    }
+                    break;
+            }
+        }
+    }
+
+    private final MyHandler mHandler;
+
+    private BatteryCallback mCallback;
+
     /**
      * The statistics we have collected organized by uids.
      */
@@ -95,6 +129,9 @@
     final SparseArray<ArrayList<StopwatchTimer>> mSensorTimers
             = new SparseArray<ArrayList<StopwatchTimer>>();
 
+    // Last partial timers we use for distributing CPU usage.
+    final ArrayList<StopwatchTimer> mLastPartialTimers = new ArrayList<StopwatchTimer>();
+
     // These are the objects that will want to do something when the device
     // is unplugged from power.
     final ArrayList<Unpluggable> mUnpluggables = new ArrayList<Unpluggable>();
@@ -240,6 +277,7 @@
     // For debugging
     public BatteryStatsImpl() {
         mFile = null;
+        mHandler = null;
     }
 
     public static interface Unpluggable {
@@ -739,7 +777,9 @@
      * State for keeping track of timing information.
      */
     public static final class StopwatchTimer extends Timer {
+        final Uid mUid;
         final ArrayList<StopwatchTimer> mTimerPool;
+
         int mNesting;
 
         /**
@@ -757,16 +797,24 @@
 
         long mTimeout;
 
-        StopwatchTimer(int type, ArrayList<StopwatchTimer> timerPool,
+        /**
+         * For partial wake locks, keep track of whether we are in the list
+         * to consume CPU cycles.
+         */
+        boolean mInList;
+
+        StopwatchTimer(Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
                 ArrayList<Unpluggable> unpluggables, Parcel in) {
             super(type, unpluggables, in);
+            mUid = uid;
             mTimerPool = timerPool;
             mUpdateTime = in.readLong();
         }
 
-        StopwatchTimer(int type, ArrayList<StopwatchTimer> timerPool,
+        StopwatchTimer(Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
                 ArrayList<Unpluggable> unpluggables) {
             super(type, unpluggables);
+            mUid = uid;
             mTimerPool = timerPool;
         }
         
@@ -1254,6 +1302,10 @@
             mWakeLockNesting++;
         }
         if (uid >= 0) {
+            if (!mHandler.hasMessages(MSG_UPDATE_WAKELOCKS)) {
+                Message m = mHandler.obtainMessage(MSG_UPDATE_WAKELOCKS);
+                mHandler.sendMessageDelayed(m, DELAY_UPDATE_WAKELOCKS);
+            }
             getUidStatsLocked(uid).noteStartWakeLocked(pid, name, type);
         }
     }
@@ -1269,10 +1321,112 @@
             }
         }
         if (uid >= 0) {
+            if (!mHandler.hasMessages(MSG_UPDATE_WAKELOCKS)) {
+                Message m = mHandler.obtainMessage(MSG_UPDATE_WAKELOCKS);
+                mHandler.sendMessageDelayed(m, DELAY_UPDATE_WAKELOCKS);
+            }
             getUidStatsLocked(uid).noteStopWakeLocked(pid, name, type);
         }
     }
 
+    public int startAddingCpuLocked() {
+        mHandler.removeMessages(MSG_UPDATE_WAKELOCKS);
+
+        if (mScreenOn) {
+            return 0;
+        }
+
+        final int N = mPartialTimers.size();
+        if (N == 0) {
+            mLastPartialTimers.clear();
+            return 0;
+        }
+
+        // How many timers should consume CPU?  Only want to include ones
+        // that have already been in the list.
+        for (int i=0; i<N; i++) {
+            StopwatchTimer st = mPartialTimers.get(i);
+            if (st.mInList) {
+                Uid uid = st.mUid;
+                // We don't include the system UID, because it so often
+                // holds wake locks at one request or another of an app.
+                if (uid != null && uid.mUid != Process.SYSTEM_UID) {
+                    return 50;
+                }
+            }
+        }
+
+        return 0;
+    }
+
+    public void finishAddingCpuLocked(int perc, int utime, int stime, long[] cpuSpeedTimes) {
+        final int N = mPartialTimers.size();
+        if (perc != 0) {
+            int num = 0;
+            for (int i=0; i<N; i++) {
+                StopwatchTimer st = mPartialTimers.get(i);
+                if (st.mInList) {
+                    Uid uid = st.mUid;
+                    // We don't include the system UID, because it so often
+                    // holds wake locks at one request or another of an app.
+                    if (uid != null && uid.mUid != Process.SYSTEM_UID) {
+                        num++;
+                    }
+                }
+            }
+            if (num != 0) {
+                for (int i=0; i<N; i++) {
+                    StopwatchTimer st = mPartialTimers.get(i);
+                    if (st.mInList) {
+                        int myUTime = utime/num;
+                        int mySTime = stime/num;
+                        utime -= myUTime;
+                        stime -= mySTime;
+                        num--;
+                        Uid uid = st.mUid;
+                        if (uid != null && uid.mUid != Process.SYSTEM_UID) {
+                            Uid.Proc proc = uid.getProcessStatsLocked("*wakelock*");
+                            proc.addCpuTimeLocked(myUTime, mySTime);
+                            proc.addSpeedStepTimes(cpuSpeedTimes);
+                        }
+                    }
+                }
+            }
+
+            // Just in case, collect any lost CPU time.
+            if (utime != 0 || stime != 0) {
+                Uid uid = getUidStatsLocked(Process.SYSTEM_UID);
+                if (uid != null) {
+                    Uid.Proc proc = uid.getProcessStatsLocked("*lost*");
+                    proc.addCpuTimeLocked(utime, stime);
+                    proc.addSpeedStepTimes(cpuSpeedTimes);
+                }
+            }
+        }
+
+        final int NL = mLastPartialTimers.size();
+        boolean diff = N != NL;
+        for (int i=0; i<NL && !diff; i++) {
+            diff |= mPartialTimers.get(i) != mLastPartialTimers.get(i);
+        }
+        if (!diff) {
+            for (int i=0; i<NL; i++) {
+                mPartialTimers.get(i).mInList = true;
+            }
+            return;
+        }
+
+        for (int i=0; i<NL; i++) {
+            mLastPartialTimers.get(i).mInList = false;
+        }
+        mLastPartialTimers.clear();
+        for (int i=0; i<N; i++) {
+            StopwatchTimer st = mPartialTimers.get(i);
+            st.mInList = true;
+            mLastPartialTimers.add(st);
+        }
+    }
+
     public void noteProcessDiedLocked(int uid, int pid) {
         Uid u = mUidStats.get(uid);
         if (u != null) {
@@ -1924,13 +2078,18 @@
 
         public Uid(int uid) {
             mUid = uid;
-            mWifiTurnedOnTimer = new StopwatchTimer(WIFI_TURNED_ON, null, mUnpluggables);
-            mFullWifiLockTimer = new StopwatchTimer(FULL_WIFI_LOCK, null, mUnpluggables);
-            mScanWifiLockTimer = new StopwatchTimer(SCAN_WIFI_LOCK, null, mUnpluggables);
-            mWifiMulticastTimer = new StopwatchTimer(WIFI_MULTICAST_ENABLED,
+            mWifiTurnedOnTimer = new StopwatchTimer(Uid.this, WIFI_TURNED_ON,
                     null, mUnpluggables);
-            mAudioTurnedOnTimer = new StopwatchTimer(AUDIO_TURNED_ON, null, mUnpluggables);
-            mVideoTurnedOnTimer = new StopwatchTimer(VIDEO_TURNED_ON, null, mUnpluggables);
+            mFullWifiLockTimer = new StopwatchTimer(Uid.this, FULL_WIFI_LOCK,
+                    null, mUnpluggables);
+            mScanWifiLockTimer = new StopwatchTimer(Uid.this, SCAN_WIFI_LOCK,
+                    null, mUnpluggables);
+            mWifiMulticastTimer = new StopwatchTimer(Uid.this, WIFI_MULTICAST_ENABLED,
+                    null, mUnpluggables);
+            mAudioTurnedOnTimer = new StopwatchTimer(Uid.this, AUDIO_TURNED_ON,
+                    null, mUnpluggables);
+            mVideoTurnedOnTimer = new StopwatchTimer(Uid.this, VIDEO_TURNED_ON,
+                    null, mUnpluggables);
         }
 
         @Override
@@ -1998,7 +2157,7 @@
             if (!mWifiTurnedOn) {
                 mWifiTurnedOn = true;
                 if (mWifiTurnedOnTimer == null) {
-                    mWifiTurnedOnTimer = new StopwatchTimer(WIFI_TURNED_ON,
+                    mWifiTurnedOnTimer = new StopwatchTimer(Uid.this, WIFI_TURNED_ON,
                             null, mUnpluggables);
                 }
                 mWifiTurnedOnTimer.startRunningLocked(BatteryStatsImpl.this);
@@ -2018,7 +2177,7 @@
             if (!mFullWifiLockOut) {
                 mFullWifiLockOut = true;
                 if (mFullWifiLockTimer == null) {
-                    mFullWifiLockTimer = new StopwatchTimer(FULL_WIFI_LOCK,
+                    mFullWifiLockTimer = new StopwatchTimer(Uid.this, FULL_WIFI_LOCK,
                             null, mUnpluggables);
                 }
                 mFullWifiLockTimer.startRunningLocked(BatteryStatsImpl.this);
@@ -2038,7 +2197,7 @@
             if (!mScanWifiLockOut) {
                 mScanWifiLockOut = true;
                 if (mScanWifiLockTimer == null) {
-                    mScanWifiLockTimer = new StopwatchTimer(SCAN_WIFI_LOCK,
+                    mScanWifiLockTimer = new StopwatchTimer(Uid.this, SCAN_WIFI_LOCK,
                             null, mUnpluggables);
                 }
                 mScanWifiLockTimer.startRunningLocked(BatteryStatsImpl.this);
@@ -2058,7 +2217,7 @@
             if (!mWifiMulticastEnabled) {
                 mWifiMulticastEnabled = true;
                 if (mWifiMulticastTimer == null) {
-                    mWifiMulticastTimer = new StopwatchTimer(WIFI_MULTICAST_ENABLED,
+                    mWifiMulticastTimer = new StopwatchTimer(Uid.this, WIFI_MULTICAST_ENABLED,
                             null, mUnpluggables);
                 }
                 mWifiMulticastTimer.startRunningLocked(BatteryStatsImpl.this);
@@ -2078,7 +2237,7 @@
             if (!mAudioTurnedOn) {
                 mAudioTurnedOn = true;
                 if (mAudioTurnedOnTimer == null) {
-                    mAudioTurnedOnTimer = new StopwatchTimer(AUDIO_TURNED_ON,
+                    mAudioTurnedOnTimer = new StopwatchTimer(Uid.this, AUDIO_TURNED_ON,
                             null, mUnpluggables);
                 }
                 mAudioTurnedOnTimer.startRunningLocked(BatteryStatsImpl.this);
@@ -2098,7 +2257,7 @@
             if (!mVideoTurnedOn) {
                 mVideoTurnedOn = true;
                 if (mVideoTurnedOnTimer == null) {
-                    mVideoTurnedOnTimer = new StopwatchTimer(VIDEO_TURNED_ON,
+                    mVideoTurnedOnTimer = new StopwatchTimer(Uid.this, VIDEO_TURNED_ON,
                             null, mUnpluggables);
                 }
                 mVideoTurnedOnTimer.startRunningLocked(BatteryStatsImpl.this);
@@ -2458,42 +2617,42 @@
             mTcpBytesSentAtLastUnplug = in.readLong();
             mWifiTurnedOn = false;
             if (in.readInt() != 0) {
-                mWifiTurnedOnTimer = new StopwatchTimer(WIFI_TURNED_ON,
+                mWifiTurnedOnTimer = new StopwatchTimer(Uid.this, WIFI_TURNED_ON,
                         null, mUnpluggables, in);
             } else {
                 mWifiTurnedOnTimer = null;
             }
             mFullWifiLockOut = false;
             if (in.readInt() != 0) {
-                mFullWifiLockTimer = new StopwatchTimer(FULL_WIFI_LOCK,
+                mFullWifiLockTimer = new StopwatchTimer(Uid.this, FULL_WIFI_LOCK,
                         null, mUnpluggables, in);
             } else {
                 mFullWifiLockTimer = null;
             }
             mScanWifiLockOut = false;
             if (in.readInt() != 0) {
-                mScanWifiLockTimer = new StopwatchTimer(SCAN_WIFI_LOCK,
+                mScanWifiLockTimer = new StopwatchTimer(Uid.this, SCAN_WIFI_LOCK,
                         null, mUnpluggables, in);
             } else {
                 mScanWifiLockTimer = null;
             }
             mWifiMulticastEnabled = false;
             if (in.readInt() != 0) {
-                mWifiMulticastTimer = new StopwatchTimer(WIFI_MULTICAST_ENABLED,
+                mWifiMulticastTimer = new StopwatchTimer(Uid.this, WIFI_MULTICAST_ENABLED,
                         null, mUnpluggables, in);
             } else {
                 mWifiMulticastTimer = null;
             }
             mAudioTurnedOn = false;
             if (in.readInt() != 0) {
-                mAudioTurnedOnTimer = new StopwatchTimer(AUDIO_TURNED_ON,
+                mAudioTurnedOnTimer = new StopwatchTimer(Uid.this, AUDIO_TURNED_ON,
                         null, mUnpluggables, in);
             } else {
                 mAudioTurnedOnTimer = null;
             }
             mVideoTurnedOn = false;
             if (in.readInt() != 0) {
-                mVideoTurnedOnTimer = new StopwatchTimer(VIDEO_TURNED_ON,
+                mVideoTurnedOnTimer = new StopwatchTimer(Uid.this, VIDEO_TURNED_ON,
                         null, mUnpluggables, in);
             } else {
                 mVideoTurnedOnTimer = null;
@@ -2540,7 +2699,7 @@
                     return null;
                 }
 
-                return new StopwatchTimer(type, pool, unpluggables, in);
+                return new StopwatchTimer(Uid.this, type, pool, unpluggables, in);
             }
 
             boolean reset() {
@@ -2616,7 +2775,7 @@
                     pool = new ArrayList<StopwatchTimer>();
                     mSensorTimers.put(mHandle, pool);
                 }
-                return new StopwatchTimer(0, pool, unpluggables, in);
+                return new StopwatchTimer(Uid.this, 0, pool, unpluggables, in);
             }
 
             boolean reset() {
@@ -3345,11 +3504,6 @@
             }
         }
 
-        public class Pid {
-            long mWakeSum;
-            long mWakeStart;
-        }
-
         /**
          * Retrieve the statistics object for a particular process, creating
          * if needed.
@@ -3364,6 +3518,10 @@
             return ps;
         }
 
+        public SparseArray<? extends Pid> getPidStats() {
+            return mPids;
+        }
+        
         public Pid getPidStatsLocked(int pid) {
             Pid p = mPids.get(pid);
             if (p == null) {
@@ -3419,21 +3577,24 @@
                 case WAKE_TYPE_PARTIAL:
                     t = wl.mTimerPartial;
                     if (t == null) {
-                        t = new StopwatchTimer(WAKE_TYPE_PARTIAL, mPartialTimers, mUnpluggables);
+                        t = new StopwatchTimer(Uid.this, WAKE_TYPE_PARTIAL,
+                                mPartialTimers, mUnpluggables);
                         wl.mTimerPartial = t;
                     }
                     return t;
                 case WAKE_TYPE_FULL:
                     t = wl.mTimerFull;
                     if (t == null) {
-                        t = new StopwatchTimer(WAKE_TYPE_FULL, mFullTimers, mUnpluggables);
+                        t = new StopwatchTimer(Uid.this, WAKE_TYPE_FULL,
+                                mFullTimers, mUnpluggables);
                         wl.mTimerFull = t;
                     }
                     return t;
                 case WAKE_TYPE_WINDOW:
                     t = wl.mTimerWindow;
                     if (t == null) {
-                        t = new StopwatchTimer(WAKE_TYPE_WINDOW, mWindowTimers, mUnpluggables);
+                        t = new StopwatchTimer(Uid.this, WAKE_TYPE_WINDOW,
+                                mWindowTimers, mUnpluggables);
                         wl.mTimerWindow = t;
                     }
                     return t;
@@ -3460,7 +3621,7 @@
                 timers = new ArrayList<StopwatchTimer>();
                 mSensorTimers.put(sensor, timers);
             }
-            t = new StopwatchTimer(BatteryStats.SENSOR, timers, mUnpluggables);
+            t = new StopwatchTimer(Uid.this, BatteryStats.SENSOR, timers, mUnpluggables);
             se.mTimer = t;
             return t;
         }
@@ -3533,25 +3694,26 @@
 
     public BatteryStatsImpl(String filename) {
         mFile = new JournaledFile(new File(filename), new File(filename + ".tmp"));
+        mHandler = new MyHandler();
         mStartCount++;
-        mScreenOnTimer = new StopwatchTimer(-1, null, mUnpluggables);
+        mScreenOnTimer = new StopwatchTimer(null, -1, null, mUnpluggables);
         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
-            mScreenBrightnessTimer[i] = new StopwatchTimer(-100-i, null, mUnpluggables);
+            mScreenBrightnessTimer[i] = new StopwatchTimer(null, -100-i, null, mUnpluggables);
         }
         mInputEventCounter = new Counter(mUnpluggables);
-        mPhoneOnTimer = new StopwatchTimer(-2, null, mUnpluggables);
+        mPhoneOnTimer = new StopwatchTimer(null, -2, null, mUnpluggables);
         for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) {
-            mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(-200-i, null, mUnpluggables);
+            mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(null, -200-i, null, mUnpluggables);
         }
-        mPhoneSignalScanningTimer = new StopwatchTimer(-200+1, null, mUnpluggables);
+        mPhoneSignalScanningTimer = new StopwatchTimer(null, -200+1, null, mUnpluggables);
         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
-            mPhoneDataConnectionsTimer[i] = new StopwatchTimer(-300-i, null, mUnpluggables);
+            mPhoneDataConnectionsTimer[i] = new StopwatchTimer(null, -300-i, null, mUnpluggables);
         }
-        mWifiOnTimer = new StopwatchTimer(-3, null, mUnpluggables);
-        mWifiRunningTimer = new StopwatchTimer(-4, null, mUnpluggables);
-        mBluetoothOnTimer = new StopwatchTimer(-5, null, mUnpluggables);
-        mAudioOnTimer = new StopwatchTimer(-6, null, mUnpluggables);
-        mVideoOnTimer = new StopwatchTimer(-7, null, mUnpluggables);
+        mWifiOnTimer = new StopwatchTimer(null, -3, null, mUnpluggables);
+        mWifiRunningTimer = new StopwatchTimer(null, -4, null, mUnpluggables);
+        mBluetoothOnTimer = new StopwatchTimer(null, -5, null, mUnpluggables);
+        mAudioOnTimer = new StopwatchTimer(null, -6, null, mUnpluggables);
+        mVideoOnTimer = new StopwatchTimer(null, -7, null, mUnpluggables);
         mOnBattery = mOnBatteryInternal = false;
         initTimes();
         mTrackBatteryPastUptime = 0;
@@ -3569,9 +3731,14 @@
 
     public BatteryStatsImpl(Parcel p) {
         mFile = null;
+        mHandler = null;
         readFromParcel(p);
     }
 
+    public void setCallback(BatteryCallback cb) {
+        mCallback = cb;
+    }
+
     public void setNumSpeedSteps(int steps) {
         if (sNumSpeedSteps == 0) sNumSpeedSteps = steps;
     }
@@ -3588,6 +3755,11 @@
     }
     
     @Override
+    public long getHistoryBaseTime() {
+        return mHistoryBaseTime;
+    }
+    
+    @Override
     public int getStartCount() {
         return mStartCount;
     }
@@ -3651,6 +3823,9 @@
     void setOnBattery(boolean onBattery, int oldStatus, int level) {
         synchronized(this) {
             boolean doWrite = false;
+            Message m = mHandler.obtainMessage(MSG_REPORT_POWER_CHANGE);
+            m.arg1 = onBattery ? 1 : 0;
+            mHandler.sendMessage(m);
             mOnBattery = mOnBatteryInternal = onBattery;
             
             long uptime = SystemClock.uptimeMillis() * 1000;
@@ -4551,26 +4726,29 @@
         mBatteryRealtime = in.readLong();
         mBatteryLastRealtime = 0;
         mScreenOn = false;
-        mScreenOnTimer = new StopwatchTimer(-1, null, mUnpluggables, in);
+        mScreenOnTimer = new StopwatchTimer(null, -1, null, mUnpluggables, in);
         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
-            mScreenBrightnessTimer[i] = new StopwatchTimer(-100-i, null, mUnpluggables, in);
+            mScreenBrightnessTimer[i] = new StopwatchTimer(null, -100-i,
+                    null, mUnpluggables, in);
         }
         mInputEventCounter = new Counter(mUnpluggables, in);
         mPhoneOn = false;
-        mPhoneOnTimer = new StopwatchTimer(-2, null, mUnpluggables, in);
+        mPhoneOnTimer = new StopwatchTimer(null, -2, null, mUnpluggables, in);
         for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) {
-            mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(-200-i, null, mUnpluggables, in);
+            mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(null, -200-i,
+                    null, mUnpluggables, in);
         }
-        mPhoneSignalScanningTimer = new StopwatchTimer(-200+1, null, mUnpluggables, in);
+        mPhoneSignalScanningTimer = new StopwatchTimer(null, -200+1, null, mUnpluggables, in);
         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
-            mPhoneDataConnectionsTimer[i] = new StopwatchTimer(-300-i, null, mUnpluggables, in);
+            mPhoneDataConnectionsTimer[i] = new StopwatchTimer(null, -300-i,
+                    null, mUnpluggables, in);
         }
         mWifiOn = false;
-        mWifiOnTimer = new StopwatchTimer(-2, null, mUnpluggables, in);
+        mWifiOnTimer = new StopwatchTimer(null, -2, null, mUnpluggables, in);
         mWifiRunning = false;
-        mWifiRunningTimer = new StopwatchTimer(-2, null, mUnpluggables, in);
+        mWifiRunningTimer = new StopwatchTimer(null, -2, null, mUnpluggables, in);
         mBluetoothOn = false;
-        mBluetoothOnTimer = new StopwatchTimer(-2, null, mUnpluggables, in);
+        mBluetoothOnTimer = new StopwatchTimer(null, -2, null, mUnpluggables, in);
         mUptime = in.readLong();
         mUptimeStart = in.readLong();
         mLastUptime = 0;
diff --git a/core/java/com/android/internal/widget/ActionBarView.java b/core/java/com/android/internal/widget/ActionBarView.java
index b9e4e46..6b3d353 100644
--- a/core/java/com/android/internal/widget/ActionBarView.java
+++ b/core/java/com/android/internal/widget/ActionBarView.java
@@ -41,6 +41,7 @@
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.AdapterView;
+import android.widget.HorizontalScrollView;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
 import android.widget.Spinner;
@@ -87,6 +88,7 @@
     private TextView mTitleView;
     private TextView mSubtitleView;
     private Spinner mSpinner;
+    private HorizontalScrollView mTabScrollView;
     private LinearLayout mTabLayout;
     private View mCustomNavView;
     
@@ -119,6 +121,8 @@
 
     private OnClickListener mHomeClickListener = null;
 
+    private OnClickListener mTabClickListener = null;
+
     public ActionBarView(Context context, AttributeSet attrs) {
         super(context, attrs);
 
@@ -346,8 +350,9 @@
                 break;
             case ActionBar.NAVIGATION_MODE_TABS:
                 if (mTabLayout != null) {
-                    removeView(mTabLayout);
+                    removeView(mTabScrollView);
                     mTabLayout = null;
+                    mTabScrollView = null;
                 }
             }
             
@@ -365,8 +370,10 @@
                 addView(mCustomNavView);
                 break;
             case ActionBar.NAVIGATION_MODE_TABS:
+                mTabScrollView = new HorizontalScrollView(getContext());
                 mTabLayout = new LinearLayout(getContext());
-                addView(mTabLayout);
+                mTabScrollView.addView(mTabLayout);
+                addView(mTabScrollView);
                 break;
             }
             mNavigationMode = mode;
@@ -401,20 +408,24 @@
     private TabView createTabView(ActionBar.Tab tab) {
         final TabView tabView = new TabView(getContext(), tab);
         tabView.setFocusable(true);
-        tabView.setOnClickListener(new TabClickListener());
+
+        if (mTabClickListener == null) {
+            mTabClickListener = new TabClickListener();
+        }
+        tabView.setOnClickListener(mTabClickListener);
         return tabView;
     }
 
     public void addTab(ActionBar.Tab tab) {
         final boolean isFirst = mTabLayout.getChildCount() == 0;
-        final TabView tabView = createTabView(tab);
+        View tabView = createTabView(tab);
         mTabLayout.addView(tabView);
         if (isFirst) {
             tabView.setSelected(true);
         }
     }
 
-    public void insertTab(ActionBar.Tab tab, int position) {
+    public void addTab(ActionBar.Tab tab, int position) {
         final boolean isFirst = mTabLayout.getChildCount() == 0;
         final TabView tabView = createTabView(tab);
         mTabLayout.addView(tabView, position);
@@ -595,8 +606,8 @@
             }
             break;
         case ActionBar.NAVIGATION_MODE_TABS:
-            if (mTabLayout != null) {
-                mTabLayout.measure(
+            if (mTabScrollView != null) {
+                mTabScrollView.measure(
                         MeasureSpec.makeMeasureSpec(availableWidth, MeasureSpec.AT_MOST),
                         MeasureSpec.makeMeasureSpec(height, MeasureSpec.AT_MOST));
             }
@@ -663,8 +674,8 @@
             }
             break;
         case ActionBar.NAVIGATION_MODE_TABS:
-            if (mTabLayout != null) {
-                x += positionChild(mTabLayout, x, y, contentHeight) + mSpacing;
+            if (mTabScrollView != null) {
+                x += positionChild(mTabScrollView, x, y, contentHeight) + mSpacing;
             }
         }
 
@@ -703,31 +714,36 @@
             super(context);
             mTab = tab;
 
-            // TODO Style tabs based on the theme
+            final View custom = tab.getCustomView();
+            if (custom != null) {
+                addView(custom);
+            } else {
+                // TODO Style tabs based on the theme
 
-            final Drawable icon = tab.getIcon();
-            final CharSequence text = tab.getText();
+                final Drawable icon = tab.getIcon();
+                final CharSequence text = tab.getText();
 
-            if (icon != null) {
-                ImageView iconView = new ImageView(context);
-                iconView.setImageDrawable(icon);
-                LayoutParams lp = new LayoutParams(LayoutParams.WRAP_CONTENT,
-                        LayoutParams.WRAP_CONTENT);
-                lp.gravity = Gravity.CENTER_VERTICAL;
-                iconView.setLayoutParams(lp);
-                addView(iconView);
-            }
+                if (icon != null) {
+                    ImageView iconView = new ImageView(context);
+                    iconView.setImageDrawable(icon);
+                    LayoutParams lp = new LayoutParams(LayoutParams.WRAP_CONTENT,
+                            LayoutParams.WRAP_CONTENT);
+                    lp.gravity = Gravity.CENTER_VERTICAL;
+                    iconView.setLayoutParams(lp);
+                    addView(iconView);
+                }
 
-            if (text != null) {
-                TextView textView = new TextView(context);
-                textView.setText(text);
-                textView.setSingleLine();
-                textView.setEllipsize(TruncateAt.END);
-                LayoutParams lp = new LayoutParams(LayoutParams.WRAP_CONTENT,
-                        LayoutParams.WRAP_CONTENT);
-                lp.gravity = Gravity.CENTER_VERTICAL;
-                textView.setLayoutParams(lp);
-                addView(textView);
+                if (text != null) {
+                    TextView textView = new TextView(context);
+                    textView.setText(text);
+                    textView.setSingleLine();
+                    textView.setEllipsize(TruncateAt.END);
+                    LayoutParams lp = new LayoutParams(LayoutParams.WRAP_CONTENT,
+                            LayoutParams.WRAP_CONTENT);
+                    lp.gravity = Gravity.CENTER_VERTICAL;
+                    textView.setLayoutParams(lp);
+                    addView(textView);
+                }
             }
 
             setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,
diff --git a/core/java/com/android/internal/widget/SlidingTab.java b/core/java/com/android/internal/widget/SlidingTab.java
index 4b56cb4..3865510 100644
--- a/core/java/com/android/internal/widget/SlidingTab.java
+++ b/core/java/com/android/internal/widget/SlidingTab.java
@@ -416,7 +416,7 @@
         }
 
         /**
-         * Start animating the slider. Note we need two animations since an Animator
+         * Start animating the slider. Note we need two animations since an ValueAnimator
          * keeps internal state of the invalidation region which is just the view being animated.
          *
          * @param anim1
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index cb0bdd3..8310e56 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -96,7 +96,6 @@
 	android/graphics/MaskFilter.cpp \
 	android/graphics/Matrix.cpp \
 	android/graphics/Movie.cpp \
-	android/graphics/NIOBuffer.cpp \
 	android/graphics/NinePatch.cpp \
 	android/graphics/NinePatchImpl.cpp \
 	android/graphics/Paint.cpp \
diff --git a/core/jni/android/graphics/Graphics.cpp b/core/jni/android/graphics/Graphics.cpp
index 578de6f..72cea65 100644
--- a/core/jni/android/graphics/Graphics.cpp
+++ b/core/jni/android/graphics/Graphics.cpp
@@ -2,7 +2,6 @@
 
 #include "jni.h"
 #include "GraphicsJNI.h"
-#include "NIOBuffer.h"
 #include "SkPicture.h"
 #include "SkRegion.h"
 #include <android_runtime/AndroidRuntime.h>
@@ -650,8 +649,6 @@
     gVMRuntime_trackExternalFreeMethodID =
                             env->GetMethodID(c, "trackExternalFree", "(J)V");
 
-    NIOBuffer::RegisterJNI(env);
-
     return 0;
 }
 
diff --git a/core/jni/android/graphics/NIOBuffer.cpp b/core/jni/android/graphics/NIOBuffer.cpp
deleted file mode 100644
index cb937a3..0000000
--- a/core/jni/android/graphics/NIOBuffer.cpp
+++ /dev/null
@@ -1,143 +0,0 @@
-#include "NIOBuffer.h"
-#include "GraphicsJNI.h"
-
-// enable this to dump each time we ref/unref a global java object (buffer)
-//
-//#define TRACE_GLOBAL_REFS
-
-//#define TRACE_ARRAY_LOCKS
-
-static jclass gNIOAccess_classID;
-static jmethodID gNIOAccess_getBasePointer;
-static jmethodID gNIOAccess_getBaseArray;
-static jmethodID gNIOAccess_getBaseArrayOffset;
-static jmethodID gNIOAccess_getRemainingBytes;
-
-void NIOBuffer::RegisterJNI(JNIEnv* env) {
-    if (0 != gNIOAccess_classID) {
-        return; // already called
-    }
-
-    jclass c = env->FindClass("java/nio/NIOAccess");
-    gNIOAccess_classID = (jclass)env->NewGlobalRef(c);
-
-    gNIOAccess_getBasePointer = env->GetStaticMethodID(gNIOAccess_classID,
-                                    "getBasePointer", "(Ljava/nio/Buffer;)J");
-    gNIOAccess_getBaseArray = env->GetStaticMethodID(gNIOAccess_classID,
-                    "getBaseArray", "(Ljava/nio/Buffer;)Ljava/lang/Object;");
-    gNIOAccess_getBaseArrayOffset = env->GetStaticMethodID(gNIOAccess_classID,
-                                "getBaseArrayOffset", "(Ljava/nio/Buffer;)I");
-    gNIOAccess_getRemainingBytes = env->GetStaticMethodID(gNIOAccess_classID,
-                                "getRemainingBytes", "(Ljava/nio/Buffer;)I");
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-#ifdef TRACE_GLOBAL_REFS
-    static int gGlobalRefs;
-#endif
-
-#ifdef TRACE_ARRAY_LOCKS
-    static int gLockCount;
-#endif
-
-NIOBuffer::NIOBuffer(JNIEnv* env, jobject buffer) {
-    fBuffer = env->NewGlobalRef(buffer);
-#ifdef TRACE_GLOBAL_REFS
-    SkDebugf("------------ newglobalref bbuffer %X %d\n", buffer, gGlobalRefs++);
-#endif
-    fLockedPtr = NULL;
-    fLockedArray = NULL;
-}
-
-NIOBuffer::~NIOBuffer() {
-    // free() needs to have already been called
-    if (NULL != fBuffer) {
-        SkDebugf("----- leaked fBuffer in NIOBuffer");
-        sk_throw();
-    }
-}
-
-void NIOBuffer::free(JNIEnv* env) {
-
-    if (NULL != fLockedPtr) {
-        SkDebugf("======= free: array still locked %x %p\n", fLockedArray, fLockedPtr);
-    }
-    
-    
-    if (NULL != fBuffer) {
-#ifdef TRACE_GLOBAL_REFS
-        SkDebugf("----------- deleteglobalref buffer %X %d\n", fBuffer, --gGlobalRefs);
-#endif
-        env->DeleteGlobalRef(fBuffer);
-        fBuffer = NULL;
-    }
-}
-
-void* NIOBuffer::lock(JNIEnv* env, int* remaining) {
-    if (NULL != fLockedPtr) {
-        SkDebugf("======= lock: array still locked %x %p\n", fLockedArray, fLockedPtr);
-    }
-
-    fLockedPtr = NULL;
-    fLockedArray = NULL;
-
-    if (NULL != remaining) {
-        *remaining = env->CallStaticIntMethod(gNIOAccess_classID,
-                                              gNIOAccess_getRemainingBytes,
-                                              fBuffer);
-        if (GraphicsJNI::hasException(env)) {
-            return NULL;
-        }
-    }
-    
-    jlong pointer = env->CallStaticLongMethod(gNIOAccess_classID,
-                                              gNIOAccess_getBasePointer,
-                                              fBuffer);
-    if (GraphicsJNI::hasException(env)) {
-        return NULL;
-    }
-    if (0 != pointer) {
-        return reinterpret_cast<void*>(pointer);
-    }
-    
-    fLockedArray = (jbyteArray)env->CallStaticObjectMethod(gNIOAccess_classID,
-                                                        gNIOAccess_getBaseArray,
-                                                        fBuffer);
-    if (GraphicsJNI::hasException(env) || NULL == fLockedArray) {
-        return NULL;
-    }
-    jint offset = env->CallStaticIntMethod(gNIOAccess_classID,
-                                           gNIOAccess_getBaseArrayOffset,
-                                           fBuffer);
-    fLockedPtr = env->GetByteArrayElements(fLockedArray, NULL);
-    if (GraphicsJNI::hasException(env)) {
-        SkDebugf("------------ failed to lockarray %x\n", fLockedArray);
-        return NULL;
-    }
-#ifdef TRACE_ARRAY_LOCKS
-    SkDebugf("------------ lockarray %x %p %d\n",
-             fLockedArray, fLockedPtr, gLockCount++);
-#endif
-    if (NULL == fLockedPtr) {
-        offset = 0;
-    }
-    return (char*)fLockedPtr + offset;
-}
-
-void NIOBuffer::unlock(JNIEnv* env, bool dataChanged) {
-    if (NULL != fLockedPtr) {
-#ifdef TRACE_ARRAY_LOCKS
-        SkDebugf("------------ unlockarray %x %p %d\n",
-                 fLockedArray, fLockedPtr, --gLockCount);
-#endif
-        env->ReleaseByteArrayElements(fLockedArray, (jbyte*)fLockedPtr,
-                                      dataChanged ? 0 : JNI_ABORT);
-        
-        fLockedPtr = NULL;
-        fLockedArray = NULL;
-    } else {
-        SkDebugf("============= unlock called with null ptr %x\n", fLockedArray);
-    }
-}
-
diff --git a/core/jni/android/graphics/NIOBuffer.h b/core/jni/android/graphics/NIOBuffer.h
deleted file mode 100644
index 36b5554..0000000
--- a/core/jni/android/graphics/NIOBuffer.h
+++ /dev/null
@@ -1,27 +0,0 @@
-#ifndef NIOBuffer_DEFINED
-#define NIOBuffer_DEFINED
-
-#include <jni.h>
-#include "SkBitmap.h"
-
-class NIOBuffer {
-public:
-    NIOBuffer(JNIEnv* env, jobject buffer);
-    // this checks to ensure that free() was called
-    ~NIOBuffer();
-
-    void* lock(JNIEnv* env, int* remaining);
-    void unlock(JNIEnv* env, bool dataChanged);
-    // must be called before destructor
-    void free(JNIEnv* env);
-
-    // call once on boot, to setup JNI globals
-    static void RegisterJNI(JNIEnv*);
-
-private:
-    jobject     fBuffer;
-    void*       fLockedPtr;
-    jbyteArray  fLockedArray;
-};
-
-#endif
diff --git a/core/jni/android_app_NativeActivity.cpp b/core/jni/android_app_NativeActivity.cpp
index 0932473a..2517a8a 100644
--- a/core/jni/android_app_NativeActivity.cpp
+++ b/core/jni/android_app_NativeActivity.cpp
@@ -127,12 +127,13 @@
     close(mDispatchKeyWrite);
 }
 
-void AInputQueue::attachLooper(ALooper* looper, ALooper_callbackFunc* callback, void* data) {
+void AInputQueue::attachLooper(ALooper* looper, int ident,
+        ALooper_callbackFunc* callback, void* data) {
     mPollLoop = static_cast<android::PollLoop*>(looper);
     mPollLoop->setLooperCallback(mConsumer.getChannel()->getReceivePipeFd(),
-            POLLIN, callback, data);
+            ident, POLLIN, callback, data);
     mPollLoop->setLooperCallback(mDispatchKeyRead,
-            POLLIN, callback, data);
+            ident, POLLIN, callback, data);
 }
 
 void AInputQueue::detachLooper() {
diff --git a/core/jni/android_database_SQLiteDatabase.cpp b/core/jni/android_database_SQLiteDatabase.cpp
index 4b3f1c0..36e9089 100644
--- a/core/jni/android_database_SQLiteDatabase.cpp
+++ b/core/jni/android_database_SQLiteDatabase.cpp
@@ -593,6 +593,9 @@
         case SQLITE_MISMATCH:
            exceptionClass = "android/database/sqlite/SQLiteDatatypeMismatchException";
            break;
+        case SQLITE_UNCLOSED:
+           exceptionClass = "android/database/sqlite/SQLiteUnfinalizedObjectsException";
+           break;
         default:
            exceptionClass = "android/database/sqlite/SQLiteException";
            break;
diff --git a/core/jni/android_util_Process.cpp b/core/jni/android_util_Process.cpp
index 7c99271..7dfb716 100644
--- a/core/jni/android_util_Process.cpp
+++ b/core/jni/android_util_Process.cpp
@@ -261,8 +261,7 @@
             continue;
         }
      
-        if (set_sched_policy(t_pid, (grp == ANDROID_TGROUP_BG_NONINTERACT) ?
-                                            SP_BACKGROUND : SP_FOREGROUND)) {
+        if (androidSetThreadSchedulingGroup(t_pid, grp) != NO_ERROR) {
             signalExceptionForGroupError(env, clazz, errno);
             break;
         }
diff --git a/core/jni/android_view_MotionEvent.cpp b/core/jni/android_view_MotionEvent.cpp
index fe247e8..93fd54f 100644
--- a/core/jni/android_view_MotionEvent.cpp
+++ b/core/jni/android_view_MotionEvent.cpp
@@ -46,6 +46,7 @@
     jfieldID mYPrecision;
     jfieldID mEdgeFlags;
     jfieldID mMetaState;
+    jfieldID mFlags;
     jfieldID mNumPointers;
     jfieldID mNumSamples;
     jfieldID mPointerIdentifiers;
@@ -91,6 +92,8 @@
             event->getEdgeFlags());
     env->SetIntField(eventObj, gMotionEventClassInfo.mMetaState,
             event->getMetaState());
+    env->SetIntField(eventObj, gMotionEventClassInfo.mFlags,
+            event->getFlags());
     env->SetIntField(eventObj, gMotionEventClassInfo.mNumPointers,
             numPointers);
     env->SetIntField(eventObj, gMotionEventClassInfo.mNumSamples,
@@ -162,6 +165,7 @@
     jfloat yPrecision = env->GetFloatField(eventObj, gMotionEventClassInfo.mYPrecision);
     jint edgeFlags = env->GetIntField(eventObj, gMotionEventClassInfo.mEdgeFlags);
     jint metaState = env->GetIntField(eventObj, gMotionEventClassInfo.mMetaState);
+    jint flags = env->GetIntField(eventObj, gMotionEventClassInfo.mFlags);
     jint numPointers = env->GetIntField(eventObj, gMotionEventClassInfo.mNumPointers);
     jint numSamples = env->GetIntField(eventObj, gMotionEventClassInfo.mNumSamples);
     jintArray pointerIdentifierArray = jintArray(env->GetObjectField(eventObj,
@@ -196,7 +200,7 @@
         samplePointerCoords[j].orientation = *(srcDataSamples++);
     }
 
-    event->initialize(deviceId, source, action, edgeFlags, metaState,
+    event->initialize(deviceId, source, action, flags, edgeFlags, metaState,
             xOffset, yOffset, xPrecision, yPrecision, downTimeNano, sampleEventTime,
             numPointers, pointerIdentifiers, samplePointerCoords);
 
@@ -281,6 +285,8 @@
             "mEdgeFlags", "I");
     GET_FIELD_ID(gMotionEventClassInfo.mMetaState, gMotionEventClassInfo.clazz,
             "mMetaState", "I");
+    GET_FIELD_ID(gMotionEventClassInfo.mFlags, gMotionEventClassInfo.clazz,
+            "mFlags", "I");
     GET_FIELD_ID(gMotionEventClassInfo.mNumPointers, gMotionEventClassInfo.clazz,
             "mNumPointers", "I");
     GET_FIELD_ID(gMotionEventClassInfo.mNumSamples, gMotionEventClassInfo.clazz,
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index c2c2138..89298ea 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -50,6 +50,8 @@
     <protected-broadcast android:name="android.intent.action.ACTION_SHUTDOWN" />
     <protected-broadcast android:name="android.intent.action.DEVICE_STORAGE_LOW" />
     <protected-broadcast android:name="android.intent.action.DEVICE_STORAGE_OK" />
+    <protected-broadcast android:name="android.intent.action.DEVICE_STORAGE_FULL" />
+    <protected-broadcast android:name="android.intent.action.DEVICE_STORAGE_NOT_FULL" />
     <protected-broadcast android:name="android.intent.action.NEW_OUTGOING_CALL" />
     <protected-broadcast android:name="android.intent.action.REBOOT" />
     <protected-broadcast android:name="android.intent.action.DOCK_EVENT" />
@@ -1311,6 +1313,10 @@
                 <action android:name="android.intent.action.ACTION_REQUEST_SHUTDOWN" />
                 <category android:name="android.intent.category.DEFAULT" />
             </intent-filter>
+            <intent-filter>
+                <action android:name="android.intent.action.REBOOT" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
         </activity>
         <activity android:name="com.android.internal.app.NetInitiatedActivity"
                 android:theme="@style/Theme.Dialog.Alert"
diff --git a/core/res/res/anim/animator_fade_in.xml b/core/res/res/anim/animator_fade_in.xml
index cd5042f..2a28b4d 100644
--- a/core/res/res/anim/animator_fade_in.xml
+++ b/core/res/res/anim/animator_fade_in.xml
@@ -17,7 +17,7 @@
 */
 -->
 
-<property xmlns:android="http://schemas.android.com/apk/res/android"
+<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
     android:interpolator="@anim/accelerate_interpolator"
     android:valueFrom="0"
     android:valueTo="1"
diff --git a/core/res/res/anim/animator_fade_out.xml b/core/res/res/anim/animator_fade_out.xml
index dfb5d9c..4db6591 100644
--- a/core/res/res/anim/animator_fade_out.xml
+++ b/core/res/res/anim/animator_fade_out.xml
@@ -17,7 +17,7 @@
 */
 -->
 
-<property xmlns:android="http://schemas.android.com/apk/res/android"
+<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
     android:interpolator="@anim/accelerate_interpolator"
     android:valueFrom="1.0"
     android:valueTo="0.0"
diff --git a/core/res/res/anim/fragment_close_enter.xml b/core/res/res/anim/fragment_close_enter.xml
index d4091e8..53afa2a 100644
--- a/core/res/res/anim/fragment_close_enter.xml
+++ b/core/res/res/anim/fragment_close_enter.xml
@@ -16,33 +16,33 @@
 ** limitations under the License.
 */
 -->
-<sequencer xmlns:android="http://schemas.android.com/apk/res/android">
-    <property
+<set xmlns:android="http://schemas.android.com/apk/res/android">
+    <objectAnimator
         android:interpolator="@anim/decelerate_interpolator"
         android:valueFrom="2"
         android:valueTo="1"
         android:valueType="floatType"
         android:propertyName="scaleX"
         android:duration="@android:integer/config_mediumAnimTime"/>
-    <property
+    <objectAnimator
         android:interpolator="@anim/decelerate_interpolator"
         android:valueFrom="2"
         android:valueTo="1"
         android:valueType="floatType"
         android:propertyName="scaleY"
         android:duration="@android:integer/config_mediumAnimTime"/>
-    <property
+    <objectAnimator
         android:interpolator="@anim/decelerate_interpolator"
         android:valueFrom="0"
         android:valueTo="1"
         android:valueType="floatType"
         android:propertyName="alpha"
         android:duration="@android:integer/config_mediumAnimTime"/>
-    <property
+    <objectAnimator
         android:interpolator="@anim/decelerate_interpolator"
         android:valueFrom="-400"
         android:valueTo="0"
         android:valueType="floatType"
         android:propertyName="translationX"
         android:duration="@android:integer/config_mediumAnimTime"/>
-</sequencer>
\ No newline at end of file
+</set>
\ No newline at end of file
diff --git a/core/res/res/anim/fragment_close_exit.xml b/core/res/res/anim/fragment_close_exit.xml
index 3e2cd22..1554a4e 100644
--- a/core/res/res/anim/fragment_close_exit.xml
+++ b/core/res/res/anim/fragment_close_exit.xml
@@ -16,33 +16,33 @@
 ** limitations under the License.
 */
 -->
-<sequencer xmlns:android="http://schemas.android.com/apk/res/android">
-    <property
+<set xmlns:android="http://schemas.android.com/apk/res/android">
+    <objectAnimator
         android:interpolator="@anim/accelerate_interpolator"
         android:valueFrom="1"
         android:valueTo=".5"
         android:valueType="floatType"
         android:propertyName="scaleX"
         android:duration="@android:integer/config_mediumAnimTime"/>
-    <property
+    <objectAnimator
         android:interpolator="@anim/accelerate_interpolator"
         android:valueFrom="1"
         android:valueTo=".5"
         android:valueType="floatType"
         android:propertyName="scaleY"
         android:duration="@android:integer/config_mediumAnimTime"/>
-    <property
+    <objectAnimator
         android:interpolator="@anim/accelerate_interpolator"
         android:valueFrom="1"
         android:valueTo="0"
         android:valueType="floatType"
         android:propertyName="alpha"
         android:duration="@android:integer/config_mediumAnimTime"/>
-    <property
+    <objectAnimator
         android:interpolator="@anim/accelerate_interpolator"
         android:valueFrom="0"
         android:valueTo="400"
         android:valueType="floatType"
         android:propertyName="translationX"
         android:duration="@android:integer/config_mediumAnimTime"/>
-</sequencer>
\ No newline at end of file
+</set>
\ No newline at end of file
diff --git a/core/res/res/anim/fragment_open_enter.xml b/core/res/res/anim/fragment_open_enter.xml
index c89001c..142f60c 100644
--- a/core/res/res/anim/fragment_open_enter.xml
+++ b/core/res/res/anim/fragment_open_enter.xml
@@ -16,31 +16,31 @@
 ** limitations under the License.
 */
 -->
-<sequencer xmlns:android="http://schemas.android.com/apk/res/android">
-    <property
+<set xmlns:android="http://schemas.android.com/apk/res/android">
+    <objectAnimator
         android:interpolator="@anim/decelerate_interpolator"
         android:valueFrom="2"
         android:valueTo="1"
         android:valueType="floatType"
         android:propertyName="scaleX"
         android:duration="@android:integer/config_mediumAnimTime"/>
-    <property
+    <objectAnimator
         android:interpolator="@anim/decelerate_interpolator"
         android:valueFrom="2"
         android:valueTo="1"
         android:valueType="floatType"
         android:propertyName="scaleY"
         android:duration="@android:integer/config_mediumAnimTime"/>
-    <property
+    <objectAnimator
         android:valueFrom="0"
         android:valueTo="1"
         android:valueType="floatType"
         android:propertyName="alpha"
         android:duration="@android:integer/config_mediumAnimTime"/>
-    <property
+    <objectAnimator
         android:valueFrom="400"
         android:valueTo="0"
         android:valueType="floatType"
         android:propertyName="translationX"
         android:duration="@android:integer/config_mediumAnimTime"/>
-</sequencer>
\ No newline at end of file
+</set>
\ No newline at end of file
diff --git a/core/res/res/anim/fragment_open_exit.xml b/core/res/res/anim/fragment_open_exit.xml
index 427fe4f..21260b9 100644
--- a/core/res/res/anim/fragment_open_exit.xml
+++ b/core/res/res/anim/fragment_open_exit.xml
@@ -16,31 +16,31 @@
 ** limitations under the License.
 */
 -->
-<sequencer xmlns:android="http://schemas.android.com/apk/res/android">
-    <property
+<set xmlns:android="http://schemas.android.com/apk/res/android">
+    <objectAnimator
         android:interpolator="@anim/accelerate_interpolator"
         android:valueFrom="1"
         android:valueTo="2"
         android:valueType="floatType"
         android:propertyName="scaleX"
         android:duration="@android:integer/config_mediumAnimTime"/>
-    <property
+    <objectAnimator
         android:interpolator="@anim/accelerate_interpolator"
         android:valueFrom="1"
         android:valueTo="2"
         android:valueType="floatType"
         android:propertyName="scaleY"
         android:duration="@android:integer/config_mediumAnimTime"/>
-    <property
+    <objectAnimator
         android:valueFrom="1"
         android:valueTo="0"
         android:valueType="floatType"
         android:propertyName="alpha"
         android:duration="@android:integer/config_mediumAnimTime"/>
-    <property
+    <objectAnimator
         android:valueFrom="0"
         android:valueTo="-400"
         android:valueType="floatType"
         android:propertyName="translationX"
         android:duration="@android:integer/config_mediumAnimTime"/>
-</sequencer>
\ No newline at end of file
+</set>
\ No newline at end of file
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 786e6b2..b476b44 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -1345,6 +1345,12 @@
              be saved. -->
         <attr name="saveEnabled" format="boolean" />
 
+        <!-- Specifies whether to filter touches when the view's window is obscured by
+             another visible window.  When set to true, the view will not receive touches
+             whenever a toast, dialog or other window appears above the view's window.
+             Refer to the {@link android.view.View} security documentation for more details. -->
+        <attr name="filterTouchesWhenObscured" format="boolean" />
+
         <!-- Defines the quality of translucent drawing caches. This property is used
              only when the drawing cache is enabled and translucent. The default value is auto. -->
         <attr name="drawingCacheQuality">
@@ -3010,7 +3016,7 @@
     </declare-styleable>
 
     <!-- ========================== -->
-    <!-- Animator class attributes -->
+    <!-- ValueAnimator class attributes -->
     <!-- ========================== -->
     <eat-comment />
 
@@ -3047,7 +3053,7 @@
     </declare-styleable>
 
     <!-- ========================== -->
-    <!-- PropertyAnimator class attributes -->
+    <!-- ObjectAnimator class attributes -->
     <!-- ========================== -->
     <eat-comment />
 
@@ -3058,11 +3064,11 @@
 
 
     <!-- ========================== -->
-    <!-- Sequencer class attributes -->
+    <!-- AnimatorSet class attributes -->
     <!-- ========================== -->
     <eat-comment />
 
-    <declare-styleable name="Sequencer">
+    <declare-styleable name="AnimatorSet">
         <!-- Name of the property being animated. -->
         <attr name="ordering">
             <!-- child animations should be played together. -->
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 1951d14..7bb56bd 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1251,6 +1251,8 @@
   <public type="attr" name="logo" id="0x010102be" />
   <public type="attr" name="xlargeScreens" id="0x010102bf" />
   <public type="attr" name="immersive" id="0x010102c0" />
+  <public type="attr" name="filterTouchesWhenObscured" id="0x010102c4" />
+
   <public-padding type="attr" name="kraken_resource_pad" end="0x01010300" />
 
   <public-padding type="id" name="kraken_resource_pad" end="0x01020040" />
@@ -1265,7 +1267,13 @@
   <public type="drawable" name="presence_audio_online" id="0x010800b1" />
   <public-padding type="drawable" name="kraken_resource_pad" end="0x01080100" />
 
+  <public type="style" name="TextAppearance.StatusBar.Title" id="0x01030065" />
+  <public type="style" name="TextAppearance.StatusBar.Icon" id="0x01030066" />
+  <public type="style" name="TextAppearance.StatusBar.EventContent" id="0x01030067" />
+  <public type="style" name="TextAppearance.StatusBar.EventContent.Title" id="0x01030068" />
+
   <public-padding type="style" name="kraken_resource_pad" end="0x01030090" />
+
   <public-padding type="string" name="kraken_resource_pad" end="0x01040020" />
   <public-padding type="integer" name="kraken_resource_pad" end="0x010e0010" />
   <public-padding type="layout" name="kraken_resource_pad" end="0x01090020" />
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index e9d799b..1981ac0 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -283,9 +283,15 @@
     <!-- Shutdown Confirmation Dialog.  When the user chooses to power off the phone, there will be a confirmation dialog.  This is the message. -->
     <string name="shutdown_confirm">Your phone will shut down.</string>
 
-    <!-- Recent Tasks dialog: title -->
+    <!-- Recent Tasks dialog: title
+     TODO: this should move to SystemUI.apk, but the code for the old 
+            recent dialog is still in the framework
+     -->
     <string name="recent_tasks_title">Recent</string>
-    <!-- Recent Tasks dialog: message when there are no recent applications -->
+    <!-- Recent Tasks dialog: message when there are no recent applications
+     TODO: this should move to SystemUI.apk, but the code for the old 
+            recent dialog is still in the framework
+     -->
     <string name="no_recent_tasks">No recent applications.</string>
 
     <!-- Title of the Global Actions Dialog -->
diff --git a/core/tests/coretests/src/android/database/sqlite/SQLiteUnfinalizedExceptionTest.java b/core/tests/coretests/src/android/database/sqlite/SQLiteUnfinalizedExceptionTest.java
new file mode 100644
index 0000000..cd2005d
--- /dev/null
+++ b/core/tests/coretests/src/android/database/sqlite/SQLiteUnfinalizedExceptionTest.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2010 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.database.sqlite;
+
+import android.content.Context;
+import android.database.sqlite.SQLiteDatabaseTest.ClassToTestSqlCompilationAndCaching;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import java.io.File;
+
+public class SQLiteUnfinalizedExceptionTest extends AndroidTestCase {
+    private SQLiteDatabase mDatabase;
+    private File mDatabaseFile;
+    private static final String TABLE_NAME = "testCursor";
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        File dbDir = getContext().getDir(this.getClass().getName(), Context.MODE_PRIVATE);
+        mDatabaseFile = new File(dbDir, "UnfinalizedExceptionTest.db");
+        if (mDatabaseFile.exists()) {
+            mDatabaseFile.delete();
+        }
+        mDatabase = SQLiteDatabase.openOrCreateDatabase(mDatabaseFile.getPath(), null);
+        assertNotNull(mDatabase);
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        mDatabase.close();
+        mDatabaseFile.delete();
+        super.tearDown();
+    }
+
+    @SmallTest
+    public void testUnfinalizedExceptionNotExcpected() {
+        mDatabase.execSQL("CREATE TABLE " + TABLE_NAME + " (i int, j int);");
+        // the above statement should be in SQLiteDatabase.mPrograms
+        // and should automatically be finalized when database is closed
+        mDatabase.lock();
+        try {
+            mDatabase.closeDatabase();
+        } finally {
+            mDatabase.unlock();
+        }
+    }
+
+    @SmallTest
+    public void testUnfinalizedException() {
+        mDatabase.execSQL("CREATE TABLE " + TABLE_NAME + " (i int, j int);");
+        mDatabase.lock();
+        mDatabase.closePendingStatements(); // clears the above from finalizer queue in mdatabase
+        mDatabase.unlock();
+        ClassToTestSqlCompilationAndCaching.create(mDatabase, "select * from "  + TABLE_NAME);
+        // since the above is NOT closed, closing database should fail
+        mDatabase.lock();
+        try {
+            mDatabase.closeDatabase();
+            fail("exception expected");
+        } catch (SQLiteUnfinalizedObjectsException e) {
+            // expected
+        } finally {
+            mDatabase.unlock();
+        }
+    }
+}
diff --git a/docs/html/guide/practices/design/performance.jd b/docs/html/guide/practices/design/performance.jd
index f22d2d3..56872a7 100644
--- a/docs/html/guide/practices/design/performance.jd
+++ b/docs/html/guide/practices/design/performance.jd
@@ -42,188 +42,39 @@
 
 <h2 id="optimize_judiciously">Optimize Judiciously</h2>
 
-<p>As you get started thinking about how to design your application, and as
-you write it, consider
-the cautionary points about optimization that Josh Bloch makes in his book
-<em>Effective Java</em>. Here's "Item 47: Optimize Judiciously", excerpted from
-the latest edition of the book with permission. Although Josh didn't have
-Android application development in mind when writing this section &mdash; for
-example, the <code style="color:black">java.awt.Component</code> class
-referenced is not available in Android, and Android uses the
-Dalvik VM, rather than a standard JVM &mdash; his points are still valid. </p>
+<p>This document is about Android-specific micro-optimization, so it assumes
+that you've already used profiling to work out exactly what code needs to be
+optimized, and that you already have a way to measure the effect (good or bad)
+of any changes you make. You only have so much engineering time to invest, so
+it's important to know you're spending it wisely.
 
-<blockquote>
+<p>(See <a href="#closing_notes">Closing Notes</a> for more on profiling and
+writing effective benchmarks.)
 
-<p>There are three aphorisms concerning optimization that everyone should know.
-They are perhaps beginning to suffer from overexposure, but in case you aren't
-yet familiar with them, here they are:</p>
+<p>This document also assumes that you made the best decisions about data
+structures and algorithms, and that you've also considered the future
+performance consequences of your API decisions. Using the right data
+structures and algorithms will make more difference than any of the advice
+here, and considering the performance consequences of your API decisions will
+make it easier to switch to better implementations later (this is more
+important for library code than for application code).
 
-<div style="padding-left:3em;padding-right:4em;">
+<p>(If you need that kind of advice, see Josh Bloch's <em>Effective Java</em>,
+item 47.)</p>
 
-<p style="margin-bottom:.5em;">More computing sins are committed in the name of
-efficiency (without necessarily achieving it) than for any other single
-reason&mdash;including blind stupidity.</p>
-<p>&mdash;William A. Wulf <span style="font-size:80%;"><sup>1</sup></span></p>
+<p>One of the trickiest problems you'll face when micro-optimizing an Android
+app is that your app is pretty much guaranteed to be running on multiple
+hardware platforms. Different versions of the VM running on different
+processors running at different speeds. It's not even generally the case
+that you can simply say "device X is a factor F faster/slower than device Y",
+and scale your results from one device to others. In particular, measurement
+on the emulator tells you very little about performance on any device. There
+are also huge differences between devices with and without a JIT: the "best"
+code for a device with a JIT is not always the best code for a device
+without.</p>
 
-<p style="margin-bottom:.5em;">We should forget about small efficiencies, say
-about 97% of the time: premature optimization is the root of all evil. </p>
-<p>&mdash;Donald E. Knuth <span style="font-size:80%;"><sup>2</sup></span></p>
-
-
-<p style="margin-bottom:.5em;">We follow two rules in the matter of optimization:</p>
-<ul style="margin-bottom:0">
-<li>Rule 1. Don't do it.</li>
-<li>Rule 2 (for experts only). Don't do it yet &mdash; that is, not until you have a
-perfectly clear and unoptimized solution. </li>
-</ul>
-<p>&mdash;M. A. Jackson <span style="font-size:80%;"><sup>3</sup></span></p>
-</div>
-
-<p>All of these aphorisms predate the Java programming language by two decades.
-They tell a deep truth about optimization: it is easy to do more harm than good,
-especially if you optimize prematurely. In the process, you may produce software
-that is neither fast nor correct and cannot easily be fixed.</p>
-
-<p>Don't sacrifice sound architectural principles for performance.
-<strong>Strive to write good programs rather than fast ones.</strong> If a good
-program is not fast enough, its architecture will allow it to be optimized. Good
-programs embody the principle of <em>information hiding</em>: where possible,
-they localize design decisions within individual modules, so individual
-decisions can be changed without affecting the remainder of the system (Item
-13).</p>
-
-<p>This does <em>not</em> mean that you can ignore performance concerns until
-your program is complete. Implementation problems can be fixed by later
-optimization, but pervasive architectural flaws that limit performance can be
-impossible to fix without rewriting the system. Changing a fundamental facet of
-your design after the fact can result in an ill-structured system that is
-difficult to maintain and evolve. Therefore you must think about performance
-during the design process.</p>
-
-<p><strong>Strive to avoid design decisions that limit performance.</strong> The
-components of a design that are most difficult to change after the fact are
-those specifying interactions between modules and with the outside world. Chief
-among these design components are APIs, wire-level protocols, and persistent
-data formats. Not only are these design components difficult or impossible to
-change after the fact, but all of them can place significant limitations on the
-performance that a system can ever achieve.</p>
-
-<p><strong>Consider the performance consequences of your API design
-decisions.</strong> Making a public type mutable may require a lot of needless
-defensive copying (Item 39). Similarly, using inheritance in a public class
-where composition would have been appropriate ties the class forever to its
-superclass, which can place artificial limits on the performance of the subclass
-(Item 16). As a final example, using an implementation type rather than an
-interface in an API ties you to a specific implementation, even though faster
-implementations may be written in the future (Item 52).</p>
-
-<p>The effects of API design on performance are very real. Consider the <code
-style="color:black">getSize</code> method in the <code
-style="color:black">java.awt.Component</code> class. The decision that this
-performance-critical method was to return a <code
-style="color:black">Dimension</code> instance, coupled with the decision that
-<code style="color:black">Dimension</code> instances are mutable, forces any
-implementation of this method to allocate a new <code
-style="color:black">Dimension</code> instance on every invocation. Even though
-allocating small objects is inexpensive on a modern VM, allocating millions of
-objects needlessly can do real harm to performance.</p>
-
-<p>In this case, several alternatives existed. Ideally, <code
-style="color:black">Dimension</code> should have been immutable (Item 15);
-alternatively, the <code style="color:black">getSize</code> method could have
-been replaced by two methods returning the individual primitive components of a
-<code style="color:black">Dimension</code> object. In fact, two such methods
-were added to the Component API in the 1.2 release for performance reasons.
-Preexisting client code, however, still uses the <code
-style="color:black">getSize</code> method and still suffers the performance
-consequences of the original API design decisions.</p>
-
-<p>Luckily, it is generally the case that good API design is consistent with
-good performance. <strong>It is a very bad idea to warp an API to achieve good
-performance.</strong> The performance issue that caused you to warp the API may
-go away in a future release of the platform or other underlying software, but
-the warped API and the support headaches that come with it will be with you for
-life.</p>
-
-<p>Once you've carefully designed your program and produced a clear, concise,
-and well-structured implementation, <em>then</em> it may be time to consider
-optimization, assuming you're not already satisfied with the performance of the
-program.</p>
-
-<p>Recall that Jackson's two rules of optimization were "Don't do it," and "(for
-experts only). Don't do it yet." He could have added one more: <strong>measure
-performance before and after each attempted optimization.</strong> You may be
-surprised by what you find. Often, attempted optimizations have no measurable
-effect on performance; sometimes, they make it worse. The main reason is that
-it's difficult to guess where your program is spending its time. The part of the
-program that you think is slow may not be at fault, in which case you'd be
-wasting your time trying to optimize it. Common wisdom says that programs spend
-80 percent of their time in 20 percent of their code.</p>
-
-<p>Profiling tools can help you decide where to focus your optimization efforts.
-Such tools give you runtime information, such as roughly how much time each
-method is consuming and how many times it is invoked. In addition to focusing
-your tuning efforts, this can alert you to the need for algorithmic changes. If
-a quadratic (or worse) algorithm lurks inside your program, no amount of tuning
-will fix the problem. You must replace the algorithm with one that is more
-efficient. The more code in the system, the more important it is to use a
-profiler. It's like looking for a needle in a haystack: the bigger the haystack,
-the more useful it is to have a metal detector. The JDK comes with a simple
-profiler and modern IDEs provide more sophisticated profiling tools.</p>
-
-<p>The need to measure the effects of attempted optimization is even greater on
-the Java platform than on more traditional platforms, because the Java
-programming language does not have a strong <em>performance model</em>. The
-relative costs of the various primitive operations are not well defined. The
-"semantic gap" between what the programmer writes and what the CPU executes is
-far greater than in traditional statically compiled languages, which makes it
-very difficult to reliably predict the performance consequences of any
-optimization. There are plenty of performance myths floating around that turn
-out to be half-truths or outright lies.</p>
-
-<p>Not only is Java's performance model ill-defined, but it varies from JVM
-implementation to JVM implementation, from release to release, and from
-processor to processor. If you will be running your program on multiple JVM
-implementations or multiple hardware platforms, it is important that you measure
-the effects of your optimization on each. Occasionally you may be forced to make
-trade-offs between performance on different JVM implementations or hardware
-platforms.</p>
-
-<p>To summarize, do not strive to write fast programs &mdash; strive to write
-good ones; speed will follow. Do think about performance issues while you're
-designing systems and especially while you're designing APIs, wire-level
-protocols, and persistent data formats. When you've finished building the
-system, measure its performance. If it's fast enough, you're done. If not,
-locate the source of the problems with the aid of a profiler, and go to work
-optimizing the relevant parts of the system. The first step is to examine your
-choice of algorithms: no amount of low-level optimization can make up for a poor
-choice of algorithm. Repeat this process as necessary, measuring the performance
-after every change, until you're satisfied.</p>
-
-<p>&mdash;Excerpted from Josh Bloch's <em>Effective Java</em>, Second Ed.
-(Addison-Wesley, 2008).</em></p>
-
-<p style="font-size:80%;margin-bottom:0;"><sup>1</sup> Wulf, W. A Case Against
-the GOTO. <em>Proceedings of the 25th ACM National
-Conference</em> 2 (1972): 791–797.</p>
-<p style="font-size:80%;margin-bottom:0;"><sup>2</sup> Knuth, Donald. Structured
-Programming with go to Statements. <em>Computing
-Surveys 6</em> (1974): 261–301.</p>
-<p style="font-size:80%"><sup>3</sup> Jackson, M. A. <em>Principles of Program
-Design</em>, Academic Press, London, 1975.
-ISBN: 0123790506.</p>
-
-</blockquote>
-
-<p>One of the trickiest problems you'll face when micro-optimizing Android
-apps is that the "if you will be running your program on ... multiple hardware
-platforms" clause above is always true. And it's not even generally the case
-that you can say "device X is a factor F faster/slower than device Y".
-This is especially true if one of the devices is the emulator, or one of the
-devices has a JIT. If you want to know how your app performs on a given device,
-you need to test it on that device. Drawing conclusions from the emulator is
-particularly dangerous, as is attempting to compare JIT versus non-JIT
-performance: the performance <em>profiles</em> can differ wildly.</p>
+<p>If you want to know how your app performs on a given device, you need to
+test on that device.</p>
 
 <a name="object_creation"></a>
 <h2>Avoid Creating Objects</h2>
@@ -566,3 +417,11 @@
 not measuring what you think you're measuring (because, say, the VM has
 managed to optimize all your code away). We highly recommend you use Caliper
 to run your own microbenchmarks.</p>
+
+<p>You may also find
+<a href="{@docRoot}guide/developing/tools/traceview.html">Traceview</a> useful
+for profiling, but it's important to realize that it currently disables the JIT,
+which may cause it to misattribute time to code that the JIT may be able to win
+back. It's especially important after making changes suggested by Traceview
+data to ensure that the resulting code actually runs faster when run without
+Traceview.
diff --git a/include/android_runtime/android_app_NativeActivity.h b/include/android_runtime/android_app_NativeActivity.h
index c388ba8..fdceb84 100644
--- a/include/android_runtime/android_app_NativeActivity.h
+++ b/include/android_runtime/android_app_NativeActivity.h
@@ -69,7 +69,7 @@
     /* Destroys the consumer and releases its input channel. */
     ~AInputQueue();
 
-    void attachLooper(ALooper* looper, ALooper_callbackFunc* callback, void* data);
+    void attachLooper(ALooper* looper, int ident, ALooper_callbackFunc* callback, void* data);
 
     void detachLooper();
 
diff --git a/include/ui/Input.h b/include/ui/Input.h
index 3fa825f..b587e94 100644
--- a/include/ui/Input.h
+++ b/include/ui/Input.h
@@ -78,6 +78,11 @@
 
     POLICY_FLAG_RAW_MASK = 0x0000ffff,
 
+    /* These flags are set by the input dispatcher. */
+
+    // Indicates that the input event was injected.
+    POLICY_FLAG_INJECTED = 0x01000000,
+
     /* These flags are set by the input reader policy as it intercepts each event. */
 
     // Indicates that the screen was off when the event was received and the event
@@ -225,6 +230,8 @@
 
     inline int32_t getAction() const { return mAction; }
 
+    inline int32_t getFlags() const { return mFlags; }
+
     inline int32_t getEdgeFlags() const { return mEdgeFlags; }
 
     inline int32_t getMetaState() const { return mMetaState; }
@@ -343,6 +350,7 @@
             int32_t deviceId,
             int32_t source,
             int32_t action,
+            int32_t flags,
             int32_t edgeFlags,
             int32_t metaState,
             float xOffset,
@@ -370,6 +378,7 @@
 
 private:
     int32_t mAction;
+    int32_t mFlags;
     int32_t mEdgeFlags;
     int32_t mMetaState;
     float mXOffset;
diff --git a/include/ui/InputDispatcher.h b/include/ui/InputDispatcher.h
index aed4fa1..f00f2db 100644
--- a/include/ui/InputDispatcher.h
+++ b/include/ui/InputDispatcher.h
@@ -84,14 +84,22 @@
          * current event is delivered to this target or a timeout occurs. */
         FLAG_SYNC = 0x01,
 
-        /* This flag indicates that a MotionEvent with ACTION_DOWN falls outside of the area of
-         * this target and so should instead be delivered as an ACTION_OUTSIDE to this target. */
+        /* This flag indicates that a MotionEvent with AMOTION_EVENT_ACTION_DOWN falls outside
+         * of the area of this target and so should instead be delivered as an
+         * AMOTION_EVENT_ACTION_OUTSIDE to this target. */
         FLAG_OUTSIDE = 0x02,
 
         /* This flag indicates that a KeyEvent or MotionEvent is being canceled.
-         * In the case of a key event, it should be delivered with KeyEvent.FLAG_CANCELED set.
-         * In the case of a motion event, it should be delivered as MotionEvent.ACTION_CANCEL. */
-        FLAG_CANCEL = 0x04
+         * In the case of a key event, it should be delivered with flag
+         * AKEY_EVENT_FLAG_CANCELED set.
+         * In the case of a motion event, it should be delivered with action
+         * AMOTION_EVENT_ACTION_CANCEL instead. */
+        FLAG_CANCEL = 0x04,
+
+        /* This flag indicates that the target of a MotionEvent is partly or wholly
+         * obscured by another visible window above it.  The motion event should be
+         * delivered with flag AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED. */
+        FLAG_WINDOW_IS_OBSCURED = 0x08,
     };
 
     // The input channel to be targeted.
@@ -139,9 +147,12 @@
     /* Notifies the system that an input channel recovered from ANR. */
     virtual void notifyInputChannelRecoveredFromANR(const sp<InputChannel>& inputChannel) = 0;
 
-    /* Gets the key repeat timeout or -1 if automatic key repeating is disabled. */
+    /* Gets the key repeat initial timeout or -1 if automatic key repeating is disabled. */
     virtual nsecs_t getKeyRepeatTimeout() = 0;
 
+    /* Gets the key repeat inter-key delay. */
+    virtual nsecs_t getKeyRepeatDelay() = 0;
+
     /* Waits for key event input targets to become available.
      * If the event is being injected, injectorPid and injectorUid should specify the
      * process id and used id of the injecting application, otherwise they should both
@@ -193,7 +204,8 @@
             uint32_t policyFlags, int32_t action, int32_t flags, int32_t keyCode,
             int32_t scanCode, int32_t metaState, nsecs_t downTime) = 0;
     virtual void notifyMotion(nsecs_t eventTime, int32_t deviceId, int32_t source,
-            uint32_t policyFlags, int32_t action, int32_t metaState, int32_t edgeFlags,
+            uint32_t policyFlags, int32_t action, int32_t flags,
+            int32_t metaState, int32_t edgeFlags,
             uint32_t pointerCount, const int32_t* pointerIds, const PointerCoords* pointerCoords,
             float xPrecision, float yPrecision, nsecs_t downTime) = 0;
 
@@ -257,7 +269,8 @@
             uint32_t policyFlags, int32_t action, int32_t flags, int32_t keyCode,
             int32_t scanCode, int32_t metaState, nsecs_t downTime);
     virtual void notifyMotion(nsecs_t eventTime, int32_t deviceId, int32_t source,
-            uint32_t policyFlags, int32_t action, int32_t metaState, int32_t edgeFlags,
+            uint32_t policyFlags, int32_t action, int32_t flags,
+            int32_t metaState, int32_t edgeFlags,
             uint32_t pointerCount, const int32_t* pointerIds, const PointerCoords* pointerCoords,
             float xPrecision, float yPrecision, nsecs_t downTime);
 
@@ -327,6 +340,7 @@
         int32_t source;
         uint32_t policyFlags;
         int32_t action;
+        int32_t flags;
         int32_t metaState;
         int32_t edgeFlags;
         float xPrecision;
@@ -458,7 +472,8 @@
                 int32_t repeatCount, nsecs_t downTime);
         MotionEntry* obtainMotionEntry(nsecs_t eventTime,
                 int32_t deviceId, int32_t source, uint32_t policyFlags, int32_t action,
-                int32_t metaState, int32_t edgeFlags, float xPrecision, float yPrecision,
+                int32_t flags, int32_t metaState, int32_t edgeFlags,
+                float xPrecision, float yPrecision,
                 nsecs_t downTime, uint32_t pointerCount,
                 const int32_t* pointerIds, const PointerCoords* pointerCoords);
         DispatchEntry* obtainDispatchEntry(EventEntry* eventEntry);
diff --git a/include/ui/InputTransport.h b/include/ui/InputTransport.h
index 31ec701..82831e2 100644
--- a/include/ui/InputTransport.h
+++ b/include/ui/InputTransport.h
@@ -135,6 +135,7 @@
 
         struct {
             int32_t action;
+            int32_t flags;
             int32_t metaState;
             int32_t edgeFlags;
             nsecs_t downTime;
@@ -218,6 +219,7 @@
             int32_t deviceId,
             int32_t source,
             int32_t action,
+            int32_t flags,
             int32_t edgeFlags,
             int32_t metaState,
             float xOffset,
diff --git a/include/utils/PollLoop.h b/include/utils/PollLoop.h
index 81230e8..bc616eb 100644
--- a/include/utils/PollLoop.h
+++ b/include/utils/PollLoop.h
@@ -111,12 +111,18 @@
      * This method can be called on any thread.
      * This method may block briefly if it needs to wake the poll loop.
      */
-    void setCallback(int fd, int events, Callback callback, void* data = NULL);
+    void setCallback(int fd, int ident, int events, Callback callback, void* data = NULL);
 
     /**
+     * Convenience for above setCallback when ident is not used.  In this case
+     * the ident is set to POLL_CALLBACK.
+     */
+    void setCallback(int fd, int events, Callback callback, void* data = NULL);
+    
+    /**
      * Like setCallback(), but for the NDK callback function.
      */
-    void setLooperCallback(int fd, int events, ALooper_callbackFunc* callback,
+    void setLooperCallback(int fd, int ident, int events, ALooper_callbackFunc* callback,
             void* data);
     
     /**
@@ -153,11 +159,13 @@
     struct RequestedCallback {
         Callback callback;
         ALooper_callbackFunc* looperCallback;
+        int ident;
         void* data;
     };
 
     struct PendingCallback {
         int fd;
+        int ident;
         int events;
         Callback callback;
         ALooper_callbackFunc* looperCallback;
@@ -185,7 +193,7 @@
     void openWakePipe();
     void closeWakePipe();
 
-    void setCallbackCommon(int fd, int events, Callback callback,
+    void setCallbackCommon(int fd, int ident, int events, Callback callback,
             ALooper_callbackFunc* looperCallback, void* data);
     ssize_t getRequestIndexLocked(int fd);
     void wakeAndLock();
diff --git a/libs/gui/SensorEventQueue.cpp b/libs/gui/SensorEventQueue.cpp
index 3396f25..7eb6da5 100644
--- a/libs/gui/SensorEventQueue.cpp
+++ b/libs/gui/SensorEventQueue.cpp
@@ -86,7 +86,7 @@
     Mutex::Autolock _l(mLock);
     if (mPollLoop == 0) {
         mPollLoop = new PollLoop(true);
-        mPollLoop->setCallback(getFd(), POLLIN, NULL, NULL);
+        mPollLoop->setCallback(getFd(), getFd(), POLLIN, NULL, NULL);
     }
     return mPollLoop;
 }
diff --git a/libs/rs/java/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java b/libs/rs/java/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java
index 4a4d837..75b8d33 100644
--- a/libs/rs/java/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java
+++ b/libs/rs/java/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java
@@ -42,8 +42,8 @@
     private Bitmap mBitmapOut;
     private Bitmap mBitmapScratch;
     private ScriptC_Threshold mScript;
-    private ScriptC_Vertical_blur mScriptVBlur;
-    private ScriptC_Horizontal_blur mScriptHBlur;
+    private ScriptC_VerticalBlur mScriptVBlur;
+    private ScriptC_HorizontalBlur mScriptHBlur;
     private int mRadius = 0;
     private SeekBar mRadiusSeekBar;
 
@@ -380,8 +380,8 @@
         mScratchPixelsAllocation1 = Allocation.createTyped(mRS, tb.create());
         mScratchPixelsAllocation2 = Allocation.createTyped(mRS, tb.create());
 
-        mScriptVBlur = new ScriptC_Vertical_blur(mRS, getResources(), R.raw.vertical_blur, false);
-        mScriptHBlur = new ScriptC_Horizontal_blur(mRS, getResources(), R.raw.horizontal_blur, false);
+        mScriptVBlur = new ScriptC_VerticalBlur(mRS, getResources(), R.raw.verticalblur, false);
+        mScriptHBlur = new ScriptC_HorizontalBlur(mRS, getResources(), R.raw.horizontalblur, false);
 
         mScript = new ScriptC_Threshold(mRS, getResources(), R.raw.threshold, false);
         mScript.set_width(mBitmapIn.getWidth());
diff --git a/libs/rs/java/tests/src/com/android/rs/test/RSTestCore.java b/libs/rs/java/tests/src/com/android/rs/test/RSTestCore.java
index c1a16dd..eb1e48b 100644
--- a/libs/rs/java/tests/src/com/android/rs/test/RSTestCore.java
+++ b/libs/rs/java/tests/src/com/android/rs/test/RSTestCore.java
@@ -30,10 +30,10 @@
     private Resources mRes;
     private RenderScriptGL mRS;
 
-    private ScriptC_Test_root mRootScript;
+    private ScriptC_TestRoot mRootScript;
 
     private boolean fp_mad() {
-        ScriptC_Fp_mad s = new ScriptC_Fp_mad(mRS, mRes, R.raw.fp_mad, true);
+        ScriptC_FpMad s = new ScriptC_FpMad(mRS, mRes, R.raw.fpmad, true);
         s.invoke_doTest(0, 0);
         return true;
     }
@@ -43,7 +43,7 @@
         mRS = rs;
         mRes = res;
 
-        mRootScript = new ScriptC_Test_root(mRS, mRes, R.raw.test_root, true);
+        mRootScript = new ScriptC_TestRoot(mRS, mRes, R.raw.testroot, true);
 
         fp_mad();
 
diff --git a/libs/rs/rsScriptC.cpp b/libs/rs/rsScriptC.cpp
index a140e22..662791d 100644
--- a/libs/rs/rsScriptC.cpp
+++ b/libs/rs/rsScriptC.cpp
@@ -17,7 +17,7 @@
 #include "rsContext.h"
 #include "rsScriptC.h"
 #include "rsMatrix.h"
-#include "../../../external/llvm/libbcc/include/bcc/bcc.h"
+#include "../../compile/libbcc/include/bcc/bcc.h"
 #include "utils/Timers.h"
 
 #include <GLES/gl.h>
diff --git a/libs/ui/Input.cpp b/libs/ui/Input.cpp
index 4973cd8..811edaf 100644
--- a/libs/ui/Input.cpp
+++ b/libs/ui/Input.cpp
@@ -129,6 +129,7 @@
         int32_t deviceId,
         int32_t source,
         int32_t action,
+        int32_t flags,
         int32_t edgeFlags,
         int32_t metaState,
         float xOffset,
@@ -142,6 +143,7 @@
         const PointerCoords* pointerCoords) {
     InputEvent::initialize(deviceId, source);
     mAction = action;
+    mFlags = flags;
     mEdgeFlags = edgeFlags;
     mMetaState = metaState;
     mXOffset = xOffset;
diff --git a/libs/ui/InputDispatcher.cpp b/libs/ui/InputDispatcher.cpp
index 886c785..df232d4 100644
--- a/libs/ui/InputDispatcher.cpp
+++ b/libs/ui/InputDispatcher.cpp
@@ -97,6 +97,7 @@
 
 void InputDispatcher::dispatchOnce() {
     nsecs_t keyRepeatTimeout = mPolicy->getKeyRepeatTimeout();
+    nsecs_t keyRepeatDelay = mPolicy->getKeyRepeatDelay();
 
     bool skipPoll = false;
     nsecs_t currentTime;
@@ -146,7 +147,7 @@
             if (mInboundQueue.isEmpty()) {
                 if (mKeyRepeatState.lastKeyEntry) {
                     if (currentTime >= mKeyRepeatState.nextRepeatTime) {
-                        processKeyRepeatLockedInterruptible(currentTime, keyRepeatTimeout);
+                        processKeyRepeatLockedInterruptible(currentTime, keyRepeatDelay);
                         skipPoll = true;
                     } else {
                         if (mKeyRepeatState.nextRepeatTime < nextWakeupTime) {
@@ -335,7 +336,7 @@
 }
 
 void InputDispatcher::processKeyRepeatLockedInterruptible(
-        nsecs_t currentTime, nsecs_t keyRepeatTimeout) {
+        nsecs_t currentTime, nsecs_t keyRepeatDelay) {
     KeyEntry* entry = mKeyRepeatState.lastKeyEntry;
 
     // Search the inbound queue for a key up corresponding to this device.
@@ -352,7 +353,7 @@
         }
     }
 
-    // Synthesize a key repeat after the repeat timeout expired.
+    // Synthesize a key repeat.
     // Reuse the repeated key entry if it is otherwise unreferenced.
     uint32_t policyFlags = entry->policyFlags & POLICY_FLAG_RAW_MASK;
     if (entry->refCount == 1) {
@@ -375,7 +376,7 @@
         entry->flags |= AKEY_EVENT_FLAG_LONG_PRESS;
     }
 
-    mKeyRepeatState.nextRepeatTime = currentTime + keyRepeatTimeout;
+    mKeyRepeatState.nextRepeatTime = currentTime + keyRepeatDelay;
 
 #if DEBUG_OUTBOUND_EVENT_DETAILS
     LOGD("processKeyRepeat - eventTime=%lld, deviceId=0x%x, source=0x%x, policyFlags=0x%x, "
@@ -392,9 +393,11 @@
 void InputDispatcher::processMotionLockedInterruptible(
         nsecs_t currentTime, MotionEntry* entry) {
 #if DEBUG_OUTBOUND_EVENT_DETAILS
-    LOGD("processMotion - eventTime=%lld, deviceId=0x%x, source=0x%x, policyFlags=0x%x, action=0x%x, "
+    LOGD("processMotion - eventTime=%lld, deviceId=0x%x, source=0x%x, policyFlags=0x%x, "
+            "action=0x%x, flags=0x%x, "
             "metaState=0x%x, edgeFlags=0x%x, xPrecision=%f, yPrecision=%f, downTime=%lld",
-            entry->eventTime, entry->deviceId, entry->source, entry->policyFlags, entry->action,
+            entry->eventTime, entry->deviceId, entry->source, entry->policyFlags,
+            entry->action, entry->flags,
             entry->metaState, entry->edgeFlags, entry->xPrecision, entry->yPrecision,
             entry->downTime);
 
@@ -406,7 +409,7 @@
     }
     for (uint32_t i = 0; i < entry->pointerCount; i++) {
         LOGD("  Pointer %d: id=%d, x=%f, y=%f, pressure=%f, size=%f, "
-                "touchMajor=%f, touchMinor=%d, toolMajor=%f, toolMinor=%f, "
+                "touchMajor=%f, touchMinor=%f, toolMajor=%f, toolMinor=%f, "
                 "orientation=%f",
                 i, entry->pointerIds[i],
                 sample->pointerCoords[i].x, sample->pointerCoords[i].y,
@@ -465,7 +468,7 @@
     mCurrentInputTargetsValid = false;
     mLock.unlock();
 
-    mReusableMotionEvent.initialize(entry->deviceId, entry->source, entry->action,
+    mReusableMotionEvent.initialize(entry->deviceId, entry->source, entry->action, entry->flags,
             entry->edgeFlags, entry->metaState,
             0, 0, entry->xPrecision, entry->yPrecision,
             entry->downTime, entry->eventTime, entry->pointerCount, entry->pointerIds,
@@ -698,12 +701,16 @@
 
         // Apply target flags.
         int32_t action = motionEntry->action;
+        int32_t flags = motionEntry->flags;
         if (dispatchEntry->targetFlags & InputTarget::FLAG_OUTSIDE) {
             action = AMOTION_EVENT_ACTION_OUTSIDE;
         }
         if (dispatchEntry->targetFlags & InputTarget::FLAG_CANCEL) {
             action = AMOTION_EVENT_ACTION_CANCEL;
         }
+        if (dispatchEntry->targetFlags & InputTarget::FLAG_WINDOW_IS_OBSCURED) {
+            flags |= AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED;
+        }
 
         // If headMotionSample is non-NULL, then it points to the first new sample that we
         // were unable to dispatch during the previous cycle so we resume dispatching from
@@ -726,7 +733,7 @@
 
         // Publish the motion event and the first motion sample.
         status = connection->inputPublisher.publishMotionEvent(motionEntry->deviceId,
-                motionEntry->source, action, motionEntry->edgeFlags, motionEntry->metaState,
+                motionEntry->source, action, flags, motionEntry->edgeFlags, motionEntry->metaState,
                 xOffset, yOffset,
                 motionEntry->xPrecision, motionEntry->yPrecision,
                 motionEntry->downTime, firstMotionSample->eventTime,
@@ -1073,18 +1080,18 @@
 }
 
 void InputDispatcher::notifyMotion(nsecs_t eventTime, int32_t deviceId, int32_t source,
-        uint32_t policyFlags, int32_t action, int32_t metaState, int32_t edgeFlags,
+        uint32_t policyFlags, int32_t action, int32_t flags, int32_t metaState, int32_t edgeFlags,
         uint32_t pointerCount, const int32_t* pointerIds, const PointerCoords* pointerCoords,
         float xPrecision, float yPrecision, nsecs_t downTime) {
 #if DEBUG_INBOUND_EVENT_DETAILS
     LOGD("notifyMotion - eventTime=%lld, deviceId=0x%x, source=0x%x, policyFlags=0x%x, "
-            "action=0x%x, metaState=0x%x, edgeFlags=0x%x, xPrecision=%f, yPrecision=%f, "
-            "downTime=%lld",
-            eventTime, deviceId, source, policyFlags, action, metaState, edgeFlags,
+            "action=0x%x, flags=0x%x, metaState=0x%x, edgeFlags=0x%x, "
+            "xPrecision=%f, yPrecision=%f, downTime=%lld",
+            eventTime, deviceId, source, policyFlags, action, flags, metaState, edgeFlags,
             xPrecision, yPrecision, downTime);
     for (uint32_t i = 0; i < pointerCount; i++) {
         LOGD("  Pointer %d: id=%d, x=%f, y=%f, pressure=%f, size=%f, "
-                "touchMajor=%f, touchMinor=%d, toolMajor=%f, toolMinor=%f, "
+                "touchMajor=%f, touchMinor=%f, toolMajor=%f, toolMinor=%f, "
                 "orientation=%f",
                 i, pointerIds[i], pointerCoords[i].x, pointerCoords[i].y,
                 pointerCoords[i].pressure, pointerCoords[i].size,
@@ -1209,7 +1216,7 @@
 
         // Just enqueue a new motion event.
         MotionEntry* newEntry = mAllocator.obtainMotionEntry(eventTime,
-                deviceId, source, policyFlags, action, metaState, edgeFlags,
+                deviceId, source, policyFlags, action, flags, metaState, edgeFlags,
                 xPrecision, yPrecision, downTime,
                 pointerCount, pointerIds, pointerCoords);
 
@@ -1359,7 +1366,7 @@
     switch (event->getType()) {
     case AINPUT_EVENT_TYPE_KEY: {
         const KeyEvent* keyEvent = static_cast<const KeyEvent*>(event);
-        uint32_t policyFlags = 0; // XXX consider adding a policy flag to track injected events
+        uint32_t policyFlags = POLICY_FLAG_INJECTED;
 
         KeyEntry* keyEntry = mAllocator.obtainKeyEntry(keyEvent->getEventTime(),
                 keyEvent->getDeviceId(), keyEvent->getSource(), policyFlags,
@@ -1371,7 +1378,7 @@
 
     case AINPUT_EVENT_TYPE_MOTION: {
         const MotionEvent* motionEvent = static_cast<const MotionEvent*>(event);
-        uint32_t policyFlags = 0; // XXX consider adding a policy flag to track injected events
+        uint32_t policyFlags = POLICY_FLAG_INJECTED;
 
         const nsecs_t* sampleEventTimes = motionEvent->getSampleEventTimes();
         const PointerCoords* samplePointerCoords = motionEvent->getSamplePointerCoords();
@@ -1379,7 +1386,8 @@
 
         MotionEntry* motionEntry = mAllocator.obtainMotionEntry(*sampleEventTimes,
                 motionEvent->getDeviceId(), motionEvent->getSource(), policyFlags,
-                motionEvent->getAction(), motionEvent->getMetaState(), motionEvent->getEdgeFlags(),
+                motionEvent->getAction(), motionEvent->getFlags(),
+                motionEvent->getMetaState(), motionEvent->getEdgeFlags(),
                 motionEvent->getXPrecision(), motionEvent->getYPrecision(),
                 motionEvent->getDownTime(), uint32_t(pointerCount),
                 motionEvent->getPointerIds(), samplePointerCoords);
@@ -1664,7 +1672,7 @@
 }
 
 InputDispatcher::MotionEntry* InputDispatcher::Allocator::obtainMotionEntry(nsecs_t eventTime,
-        int32_t deviceId, int32_t source, uint32_t policyFlags, int32_t action,
+        int32_t deviceId, int32_t source, uint32_t policyFlags, int32_t action, int32_t flags,
         int32_t metaState, int32_t edgeFlags, float xPrecision, float yPrecision,
         nsecs_t downTime, uint32_t pointerCount,
         const int32_t* pointerIds, const PointerCoords* pointerCoords) {
@@ -1676,6 +1684,7 @@
     entry->source = source;
     entry->policyFlags = policyFlags;
     entry->action = action;
+    entry->flags = flags;
     entry->metaState = metaState;
     entry->edgeFlags = edgeFlags;
     entry->xPrecision = xPrecision;
diff --git a/libs/ui/InputReader.cpp b/libs/ui/InputReader.cpp
index 8ffb48d..d57b38c 100644
--- a/libs/ui/InputReader.cpp
+++ b/libs/ui/InputReader.cpp
@@ -1153,7 +1153,7 @@
     int32_t pointerId = 0;
 
     getDispatcher()->notifyMotion(when, getDeviceId(), AINPUT_SOURCE_TRACKBALL, policyFlags,
-            motionEventAction, metaState, AMOTION_EVENT_EDGE_FLAG_NONE,
+            motionEventAction, 0, metaState, AMOTION_EVENT_EDGE_FLAG_NONE,
             1, & pointerId, pointerCoords, mXPrecision, mYPrecision, downTime);
 }
 
@@ -2324,7 +2324,7 @@
     } // release lock
 
     getDispatcher()->notifyMotion(when, getDeviceId(), AINPUT_SOURCE_TOUCHSCREEN, policyFlags,
-            motionEventAction, getContext()->getGlobalMetaState(), motionEventEdgeFlags,
+            motionEventAction, 0, getContext()->getGlobalMetaState(), motionEventEdgeFlags,
             pointerCount, pointerIds, pointerCoords,
             xPrecision, yPrecision, mDownTime);
 }
diff --git a/libs/ui/InputTransport.cpp b/libs/ui/InputTransport.cpp
index cf0f63e..4c402dc 100644
--- a/libs/ui/InputTransport.cpp
+++ b/libs/ui/InputTransport.cpp
@@ -318,8 +318,8 @@
         nsecs_t downTime,
         nsecs_t eventTime) {
 #if DEBUG_TRANSPORT_ACTIONS
-    LOGD("channel '%s' publisher ~ publishKeyEvent: deviceId=%d, source=%d, "
-            "action=%d, flags=%d, keyCode=%d, scanCode=%d, metaState=%d, repeatCount=%d,"
+    LOGD("channel '%s' publisher ~ publishKeyEvent: deviceId=%d, source=0x%x, "
+            "action=0x%x, flags=0x%x, keyCode=%d, scanCode=%d, metaState=0x%x, repeatCount=%d,"
             "downTime=%lld, eventTime=%lld",
             mChannel->getName().string(),
             deviceId, source, action, flags, keyCode, scanCode, metaState, repeatCount,
@@ -346,6 +346,7 @@
         int32_t deviceId,
         int32_t source,
         int32_t action,
+        int32_t flags,
         int32_t edgeFlags,
         int32_t metaState,
         float xOffset,
@@ -358,12 +359,12 @@
         const int32_t* pointerIds,
         const PointerCoords* pointerCoords) {
 #if DEBUG_TRANSPORT_ACTIONS
-    LOGD("channel '%s' publisher ~ publishMotionEvent: deviceId=%d, source=%d, "
-            "action=%d, edgeFlags=%d, metaState=%d, xOffset=%f, yOffset=%f, "
+    LOGD("channel '%s' publisher ~ publishMotionEvent: deviceId=%d, source=0x%x, "
+            "action=0x%x, flags=0x%x, edgeFlags=0x%x, metaState=0x%x, xOffset=%f, yOffset=%f, "
             "xPrecision=%f, yPrecision=%f, downTime=%lld, eventTime=%lld, "
             "pointerCount=%d",
             mChannel->getName().string(),
-            deviceId, source, action, edgeFlags, metaState, xOffset, yOffset,
+            deviceId, source, action, flags, edgeFlags, metaState, xOffset, yOffset,
             xPrecision, yPrecision, downTime, eventTime, pointerCount);
 #endif
 
@@ -379,6 +380,7 @@
     }
 
     mSharedMessage->motion.action = action;
+    mSharedMessage->motion.flags = flags;
     mSharedMessage->motion.edgeFlags = edgeFlags;
     mSharedMessage->motion.metaState = metaState;
     mSharedMessage->motion.xOffset = xOffset;
@@ -664,6 +666,7 @@
             mSharedMessage->deviceId,
             mSharedMessage->source,
             mSharedMessage->motion.action,
+            mSharedMessage->motion.flags,
             mSharedMessage->motion.edgeFlags,
             mSharedMessage->motion.metaState,
             mSharedMessage->motion.xOffset,
diff --git a/libs/ui/tests/InputPublisherAndConsumer_test.cpp b/libs/ui/tests/InputPublisherAndConsumer_test.cpp
index 3bc21fa..952b974 100644
--- a/libs/ui/tests/InputPublisherAndConsumer_test.cpp
+++ b/libs/ui/tests/InputPublisherAndConsumer_test.cpp
@@ -138,6 +138,7 @@
     const int32_t deviceId = 1;
     const int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
     const int32_t action = AMOTION_EVENT_ACTION_MOVE;
+    const int32_t flags = AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED;
     const int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_TOP;
     const int32_t metaState = AMETA_ALT_LEFT_ON | AMETA_ALT_ON;
     const float xOffset = -10;
@@ -167,7 +168,7 @@
         }
     }
 
-    status = mPublisher->publishMotionEvent(deviceId, source, action, edgeFlags,
+    status = mPublisher->publishMotionEvent(deviceId, source, action, flags, edgeFlags,
             metaState, xOffset, yOffset, xPrecision, yPrecision,
             downTime, sampleEventTimes[0], pointerCount, pointerIds, samplePointerCoords.array());
     ASSERT_EQ(OK, status)
@@ -213,6 +214,7 @@
     EXPECT_EQ(deviceId, motionEvent->getDeviceId());
     EXPECT_EQ(source, motionEvent->getSource());
     EXPECT_EQ(action, motionEvent->getAction());
+    EXPECT_EQ(flags, motionEvent->getFlags());
     EXPECT_EQ(edgeFlags, motionEvent->getEdgeFlags());
     EXPECT_EQ(metaState, motionEvent->getMetaState());
     EXPECT_EQ(xPrecision, motionEvent->getXPrecision());
@@ -322,12 +324,12 @@
     int32_t pointerIds[pointerCount] = { 0 };
     PointerCoords pointerCoords[pointerCount] = { { 0, 0, 0, 0, 0, 0, 0, 0, 0 } };
 
-    status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
             pointerCount, pointerIds, pointerCoords);
     ASSERT_EQ(OK, status)
             << "publisher publishMotionEvent should return OK";
 
-    status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
             pointerCount, pointerIds, pointerCoords);
     ASSERT_EQ(INVALID_OPERATION, status)
             << "publisher publishMotionEvent should return INVALID_OPERATION because ";
@@ -342,7 +344,7 @@
     int32_t pointerIds[pointerCount];
     PointerCoords pointerCoords[pointerCount];
 
-    status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
             pointerCount, pointerIds, pointerCoords);
     ASSERT_EQ(BAD_VALUE, status)
             << "publisher publishMotionEvent should return BAD_VALUE";
@@ -356,7 +358,7 @@
     int32_t pointerIds[pointerCount];
     PointerCoords pointerCoords[pointerCount];
 
-    status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
             pointerCount, pointerIds, pointerCoords);
     ASSERT_EQ(BAD_VALUE, status)
             << "publisher publishMotionEvent should return BAD_VALUE";
@@ -402,7 +404,7 @@
     PointerCoords pointerCoords[pointerCount];
 
     status = mPublisher->publishMotionEvent(0, 0, AMOTION_EVENT_ACTION_DOWN,
-            0, 0, 0, 0, 0, 0, 0, 0, pointerCount, pointerIds, pointerCoords);
+            0, 0, 0, 0, 0, 0, 0, 0, 0, pointerCount, pointerIds, pointerCoords);
     ASSERT_EQ(OK, status);
 
     status = mPublisher->appendMotionSample(0, pointerCoords);
@@ -419,7 +421,7 @@
     PointerCoords pointerCoords[pointerCount];
 
     status = mPublisher->publishMotionEvent(0, 0, AMOTION_EVENT_ACTION_MOVE,
-            0, 0, 0, 0, 0, 0, 0, 0, pointerCount, pointerIds, pointerCoords);
+            0, 0, 0, 0, 0, 0, 0, 0, 0, pointerCount, pointerIds, pointerCoords);
     ASSERT_EQ(OK, status);
 
     status = mPublisher->sendDispatchSignal();
@@ -446,7 +448,7 @@
     PointerCoords pointerCoords[pointerCount];
 
     status = mPublisher->publishMotionEvent(0, 0, AMOTION_EVENT_ACTION_MOVE,
-            0, 0, 0, 0, 0, 0, 0, 0, pointerCount, pointerIds, pointerCoords);
+            0, 0, 0, 0, 0, 0, 0, 0, 0, pointerCount, pointerIds, pointerCoords);
     ASSERT_EQ(OK, status);
 
     for (int count = 1;; count++) {
diff --git a/libs/utils/PollLoop.cpp b/libs/utils/PollLoop.cpp
index f740fa0..6d3eeee 100644
--- a/libs/utils/PollLoop.cpp
+++ b/libs/utils/PollLoop.cpp
@@ -95,6 +95,7 @@
     RequestedCallback requestedCallback;
     requestedCallback.callback = NULL;
     requestedCallback.looperCallback = NULL;
+    requestedCallback.ident = 0;
     requestedCallback.data = NULL;
     mRequestedCallbacks.insertAt(requestedCallback, 0);
 }
@@ -116,7 +117,7 @@
         mPendingFdsPos++;
         if (outEvents != NULL) *outEvents = pending.events;
         if (outData != NULL) *outData = pending.data;
-        return pending.fd;
+        return pending.ident;
     }
     
     mLock.lock();
@@ -182,6 +183,7 @@
             const RequestedCallback& requestedCallback = mRequestedCallbacks.itemAt(i);
             PendingCallback pending;
             pending.fd = requestedFd.fd;
+            pending.ident = requestedCallback.ident;
             pending.events = revents;
             pending.callback = requestedCallback.callback;
             pending.looperCallback = requestedCallback.looperCallback;
@@ -191,7 +193,7 @@
                 mPendingCallbacks.push(pending);
             } else if (pending.fd != mWakeReadPipeFd) {
                 if (result == POLL_CALLBACK) {
-                    result = pending.fd;
+                    result = pending.ident;
                     if (outEvents != NULL) *outEvents = pending.events;
                     if (outData != NULL) *outData = pending.data;
                 } else {
@@ -268,16 +270,20 @@
     return mAllowNonCallbacks;
 }
 
+void PollLoop::setCallback(int fd, int ident, int events, Callback callback, void* data) {
+    setCallbackCommon(fd, ident, events, callback, NULL, data);
+}
+
 void PollLoop::setCallback(int fd, int events, Callback callback, void* data) {
-    setCallbackCommon(fd, events, callback, NULL, data);
+    setCallbackCommon(fd, POLL_CALLBACK, events, callback, NULL, data);
 }
 
-void PollLoop::setLooperCallback(int fd, int events, ALooper_callbackFunc* callback,
+void PollLoop::setLooperCallback(int fd, int ident, int events, ALooper_callbackFunc* callback,
         void* data) {
-    setCallbackCommon(fd, events, NULL, callback, data);
+    setCallbackCommon(fd, ident, events, NULL, callback, data);
 }
 
-void PollLoop::setCallbackCommon(int fd, int events, Callback callback,
+void PollLoop::setCallbackCommon(int fd, int ident, int events, Callback callback,
         ALooper_callbackFunc* looperCallback, void* data) {
 
 #if DEBUG_CALLBACKS
@@ -305,6 +311,7 @@
     RequestedCallback requestedCallback;
     requestedCallback.callback = callback;
     requestedCallback.looperCallback = looperCallback;
+    requestedCallback.ident = ident;
     requestedCallback.data = data;
 
     ssize_t index = getRequestIndexLocked(fd);
diff --git a/libs/utils/Threads.cpp b/libs/utils/Threads.cpp
index 2b1f490..e5ece8e 100644
--- a/libs/utils/Threads.cpp
+++ b/libs/utils/Threads.cpp
@@ -21,6 +21,7 @@
 #include <utils/Log.h>
 
 #include <cutils/sched_policy.h>
+#include <cutils/properties.h>
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -57,7 +58,7 @@
 // ----------------------------------------------------------------------------
 
 /*
- * Create and run a new thead.
+ * Create and run a new thread.
  *
  * We create it "detached", so it cleans up after itself.
  */
@@ -280,6 +281,22 @@
 #endif
 }
 
+#if defined(HAVE_PTHREADS)
+static pthread_once_t gDoSchedulingGroupOnce = PTHREAD_ONCE_INIT;
+static bool gDoSchedulingGroup = true;
+
+static void checkDoSchedulingGroup(void) {
+    char buf[PROPERTY_VALUE_MAX];
+    int len = property_get("debug.sys.noschedgroups", buf, "");
+    if (len > 0) {
+        int temp;
+        if (sscanf(buf, "%d", &temp) == 1) {
+            gDoSchedulingGroup = temp == 0;
+        }
+    }
+}
+#endif
+
 int androidSetThreadSchedulingGroup(pid_t tid, int grp)
 {
     if (grp > ANDROID_TGROUP_MAX || grp < 0) { 
@@ -287,9 +304,12 @@
     }
 
 #if defined(HAVE_PTHREADS)
-    if (set_sched_policy(tid, (grp == ANDROID_TGROUP_BG_NONINTERACT) ?
-                                      SP_BACKGROUND : SP_FOREGROUND)) {
-        return PERMISSION_DENIED;
+    pthread_once(&gDoSchedulingGroupOnce, checkDoSchedulingGroup);
+    if (gDoSchedulingGroup) {
+        if (set_sched_policy(tid, (grp == ANDROID_TGROUP_BG_NONINTERACT) ?
+                                          SP_BACKGROUND : SP_FOREGROUND)) {
+            return PERMISSION_DENIED;
+        }
     }
 #endif
     
@@ -303,10 +323,13 @@
 #if defined(HAVE_PTHREADS)
     int lasterr = 0;
 
-    if (pri >= ANDROID_PRIORITY_BACKGROUND) {
-        rc = set_sched_policy(tid, SP_BACKGROUND);
-    } else if (getpriority(PRIO_PROCESS, tid) >= ANDROID_PRIORITY_BACKGROUND) {
-        rc = set_sched_policy(tid, SP_FOREGROUND);
+    pthread_once(&gDoSchedulingGroupOnce, checkDoSchedulingGroup);
+    if (gDoSchedulingGroup) {
+        if (pri >= ANDROID_PRIORITY_BACKGROUND) {
+            rc = set_sched_policy(tid, SP_BACKGROUND);
+        } else if (getpriority(PRIO_PROCESS, tid) >= ANDROID_PRIORITY_BACKGROUND) {
+            rc = set_sched_policy(tid, SP_FOREGROUND);
+        }
     }
 
     if (rc) {
diff --git a/libs/utils/ZipFileRO.cpp b/libs/utils/ZipFileRO.cpp
index a0e01c6..2d53136 100644
--- a/libs/utils/ZipFileRO.cpp
+++ b/libs/utils/ZipFileRO.cpp
@@ -636,7 +636,7 @@
         memcpy(buffer, ptr, uncompLen);
     } else {
         if (!inflateBuffer(buffer, ptr, uncompLen, compLen))
-            goto unmap;
+            goto bail;
     }
 
     if (compLen > kSequentialMin)
@@ -644,8 +644,6 @@
 
     result = true;
 
-unmap:
-    file->release();
 bail:
     return result;
 }
@@ -669,7 +667,7 @@
 
     getEntryInfo(entry, &method, &uncompLen, &compLen, &offset, NULL, NULL);
 
-    FileMap* file = createEntryFileMap(entry);
+    const FileMap* file = createEntryFileMap(entry);
     if (file == NULL) {
         goto bail;
     }
@@ -680,23 +678,21 @@
         ssize_t actual = write(fd, ptr, uncompLen);
         if (actual < 0) {
             LOGE("Write failed: %s\n", strerror(errno));
-            goto unmap;
+            goto bail;
         } else if ((size_t) actual != uncompLen) {
             LOGE("Partial write during uncompress (%zd of %zd)\n",
                 (size_t)actual, (size_t)uncompLen);
-            goto unmap;
+            goto bail;
         } else {
             LOGI("+++ successful write\n");
         }
     } else {
         if (!inflateBuffer(fd, ptr, uncompLen, compLen))
-            goto unmap;
+            goto bail;
     }
 
     result = true;
 
-unmap:
-    file->release();
 bail:
     return result;
 }
diff --git a/media/java/android/media/MtpDatabase.java b/media/java/android/media/MtpDatabase.java
index 9016e68..3487b0f 100644
--- a/media/java/android/media/MtpDatabase.java
+++ b/media/java/android/media/MtpDatabase.java
@@ -26,7 +26,7 @@
 import android.os.RemoteException;
 import android.provider.MediaStore.Audio;
 import android.provider.MediaStore.MediaColumns;
-import android.provider.MediaStore.MtpObjects;
+import android.provider.MediaStore.Files;
 import android.provider.Mtp;
 import android.util.Log;
 
@@ -53,26 +53,26 @@
     private final int mStorageID = 0x00010001;
 
     private static final String[] ID_PROJECTION = new String[] {
-            MtpObjects.ObjectColumns._ID, // 0
+            Files.FileColumns._ID, // 0
     };
     private static final String[] PATH_SIZE_PROJECTION = new String[] {
-            MtpObjects.ObjectColumns._ID, // 0
-            MtpObjects.ObjectColumns.DATA, // 1
-            MtpObjects.ObjectColumns.SIZE, // 2
+            Files.FileColumns._ID, // 0
+            Files.FileColumns.DATA, // 1
+            Files.FileColumns.SIZE, // 2
     };
     private static final String[] OBJECT_INFO_PROJECTION = new String[] {
-            MtpObjects.ObjectColumns._ID, // 0
-            MtpObjects.ObjectColumns.DATA, // 1
-            MtpObjects.ObjectColumns.FORMAT, // 2
-            MtpObjects.ObjectColumns.PARENT, // 3
-            MtpObjects.ObjectColumns.SIZE, // 4
-            MtpObjects.ObjectColumns.DATE_MODIFIED, // 5
+            Files.FileColumns._ID, // 0
+            Files.FileColumns.DATA, // 1
+            Files.FileColumns.FORMAT, // 2
+            Files.FileColumns.PARENT, // 3
+            Files.FileColumns.SIZE, // 4
+            Files.FileColumns.DATE_MODIFIED, // 5
     };
-    private static final String ID_WHERE = MtpObjects.ObjectColumns._ID + "=?";
-    private static final String PATH_WHERE = MtpObjects.ObjectColumns.DATA + "=?";
-    private static final String PARENT_WHERE = MtpObjects.ObjectColumns.PARENT + "=?";
+    private static final String ID_WHERE = Files.FileColumns._ID + "=?";
+    private static final String PATH_WHERE = Files.FileColumns.DATA + "=?";
+    private static final String PARENT_WHERE = Files.FileColumns.PARENT + "=?";
     private static final String PARENT_FORMAT_WHERE = PARENT_WHERE + " AND "
-                                            + MtpObjects.ObjectColumns.FORMAT + "=?";
+                                            + Files.FileColumns.FORMAT + "=?";
 
     private static final String[] DEVICE_PROPERTY_PROJECTION = new String[] { "_id", "value" };
     private  static final String DEVICE_PROPERTY_WHERE = "code=?";
@@ -89,7 +89,7 @@
         mContext = context;
         mMediaProvider = context.getContentResolver().acquireProvider("media");
         mVolumeName = volumeName;
-        mObjectsUri = MtpObjects.getContentUri(volumeName);
+        mObjectsUri = Files.getContentUri(volumeName);
         mMediaScanner = new MediaScanner(context);
         openDevicePropertiesDatabase(context);
     }
@@ -123,12 +123,12 @@
                          int storage, long size, long modified) {
         mDatabaseModified = true;
         ContentValues values = new ContentValues();
-        values.put(MtpObjects.ObjectColumns.DATA, path);
-        values.put(MtpObjects.ObjectColumns.FORMAT, format);
-        values.put(MtpObjects.ObjectColumns.PARENT, parent);
+        values.put(Files.FileColumns.DATA, path);
+        values.put(Files.FileColumns.FORMAT, format);
+        values.put(Files.FileColumns.PARENT, parent);
         // storage is ignored for now
-        values.put(MtpObjects.ObjectColumns.SIZE, size);
-        values.put(MtpObjects.ObjectColumns.DATE_MODIFIED, modified);
+        values.put(Files.FileColumns.SIZE, size);
+        values.put(Files.FileColumns.DATE_MODIFIED, modified);
 
         try {
             Uri uri = mMediaProvider.insert(mObjectsUri, values);
@@ -244,25 +244,8 @@
 
     private int[] getSupportedPlaybackFormats() {
         return new int[] {
-            MtpConstants.FORMAT_ASSOCIATION,
-            MtpConstants.FORMAT_MP3,
-            MtpConstants.FORMAT_MPEG,
-            MtpConstants.FORMAT_EXIF_JPEG,
-            MtpConstants.FORMAT_TIFF_EP,
-            MtpConstants.FORMAT_GIF,
-            MtpConstants.FORMAT_JFIF,
-            MtpConstants.FORMAT_PNG,
-            MtpConstants.FORMAT_TIFF,
-            MtpConstants.FORMAT_WMA,
-            MtpConstants.FORMAT_OGG,
-            MtpConstants.FORMAT_AAC,
-            MtpConstants.FORMAT_MP4_CONTAINER,
-            MtpConstants.FORMAT_MP2,
-            MtpConstants.FORMAT_3GP_CONTAINER,
-            MtpConstants.FORMAT_ABSTRACT_AV_PLAYLIST,
-            MtpConstants.FORMAT_WPL_PLAYLIST,
-            MtpConstants.FORMAT_M3U_PLAYLIST,
-            MtpConstants.FORMAT_PLS_PLAYLIST,
+            // allow transfering arbitrary files
+            MtpConstants.FORMAT_UNDEFINED,
         };
     }
 
@@ -299,24 +282,24 @@
                 outIntValue[0] = mStorageID;
                 return MtpConstants.RESPONSE_OK;
             case MtpConstants.PROPERTY_OBJECT_FORMAT:
-                column = MtpObjects.ObjectColumns.FORMAT;
+                column = Files.FileColumns.FORMAT;
                 break;
             case MtpConstants.PROPERTY_PROTECTION_STATUS:
                 // protection status is always 0
                 outIntValue[0] = 0;
                 return MtpConstants.RESPONSE_OK;
             case MtpConstants.PROPERTY_OBJECT_SIZE:
-                column = MtpObjects.ObjectColumns.SIZE;
+                column = Files.FileColumns.SIZE;
                 break;
             case MtpConstants.PROPERTY_OBJECT_FILE_NAME:
-                column = MtpObjects.ObjectColumns.DATA;
+                column = Files.FileColumns.DATA;
                 isString = true;
                 break;
             case MtpConstants.PROPERTY_DATE_MODIFIED:
-                column = MtpObjects.ObjectColumns.DATE_MODIFIED;
+                column = Files.FileColumns.DATE_MODIFIED;
                 break;
             case MtpConstants.PROPERTY_PARENT_OBJECT:
-                column = MtpObjects.ObjectColumns.PARENT;
+                column = Files.FileColumns.PARENT;
                 break;
             case MtpConstants.PROPERTY_PERSISTENT_UID:
                 // PUID is concatenation of storageID and object handle
@@ -333,7 +316,7 @@
         try {
             // for now we are only reading properties from the "objects" table
             c = mMediaProvider.query(mObjectsUri,
-                            new String [] { MtpObjects.ObjectColumns._ID, column },
+                            new String [] { Files.FileColumns._ID, column },
                             ID_WHERE, new String[] { Integer.toString(handle) }, null);
             if (c != null && c.moveToNext()) {
                 if (isString) {
@@ -496,7 +479,7 @@
     private int deleteFile(int handle) {
         Log.d(TAG, "deleteFile: " + handle);
         mDatabaseModified = true;
-        Uri uri = MtpObjects.getContentUri(mVolumeName, handle);
+        Uri uri = Files.getContentUri(mVolumeName, handle);
         try {
             if (mMediaProvider.delete(uri, null, null) == 1) {
                 return MtpConstants.RESPONSE_OK;
@@ -511,7 +494,7 @@
 
     private int[] getObjectReferences(int handle) {
         Log.d(TAG, "getObjectReferences for: " + handle);
-        Uri uri = MtpObjects.getReferencesUri(mVolumeName, handle);
+        Uri uri = Files.getReferencesUri(mVolumeName, handle);
         Cursor c = null;
         try {
             c = mMediaProvider.query(uri, ID_PROJECTION, null, null, null);
@@ -539,12 +522,12 @@
 
     private int setObjectReferences(int handle, int[] references) {
         mDatabaseModified = true;
-        Uri uri = MtpObjects.getReferencesUri(mVolumeName, handle);
+        Uri uri = Files.getReferencesUri(mVolumeName, handle);
         int count = references.length;
         ContentValues[] valuesList = new ContentValues[count];
         for (int i = 0; i < count; i++) {
             ContentValues values = new ContentValues();
-            values.put(MtpObjects.ObjectColumns._ID, references[i]);
+            values.put(Files.FileColumns._ID, references[i]);
             valuesList[i] = values;
         }
         try {
diff --git a/media/libstagefright/colorconversion/SoftwareRenderer.cpp b/media/libstagefright/colorconversion/SoftwareRenderer.cpp
index 507fa5a..c204a94 100644
--- a/media/libstagefright/colorconversion/SoftwareRenderer.cpp
+++ b/media/libstagefright/colorconversion/SoftwareRenderer.cpp
@@ -106,7 +106,12 @@
 void SoftwareRenderer::render(
         const void *data, size_t size, void *platformPrivate) {
     android_native_buffer_t *buf;
-    CHECK_EQ(0, mSurface->dequeueBuffer(mSurface.get(), &buf));
+    int err;
+    if ((err = mSurface->dequeueBuffer(mSurface.get(), &buf)) != 0) {
+        LOGW("Surface::dequeueBuffer returned error %d", err);
+        return;
+    }
+
     CHECK_EQ(0, mSurface->lockBuffer(mSurface.get(), buf));
 
     GraphicBufferMapper &mapper = GraphicBufferMapper::get();
@@ -186,7 +191,9 @@
 
     CHECK_EQ(0, mapper.unlock(buf->handle));
 
-    CHECK_EQ(0, mSurface->queueBuffer(mSurface.get(), buf));
+    if ((err = mSurface->queueBuffer(mSurface.get(), buf)) != 0) {
+        LOGW("Surface::queueBuffer returned error %d", err);
+    }
     buf = NULL;
 }
 
diff --git a/native/android/input.cpp b/native/android/input.cpp
index 379960a..57f0072 100644
--- a/native/android/input.cpp
+++ b/native/android/input.cpp
@@ -84,6 +84,10 @@
     return static_cast<const MotionEvent*>(motion_event)->getAction();
 }
 
+int32_t AMotionEvent_getFlags(const AInputEvent* motion_event) {
+    return static_cast<const MotionEvent*>(motion_event)->getFlags();
+}
+
 int32_t AMotionEvent_getMetaState(const AInputEvent* motion_event) {
     return static_cast<const MotionEvent*>(motion_event)->getMetaState();
 }
@@ -246,8 +250,8 @@
 
 
 void AInputQueue_attachLooper(AInputQueue* queue, ALooper* looper,
-        ALooper_callbackFunc* callback, void* data) {
-    queue->attachLooper(looper, callback, data);
+        int ident, ALooper_callbackFunc* callback, void* data) {
+    queue->attachLooper(looper, ident, callback, data);
 }
 
 void AInputQueue_detachLooper(AInputQueue* queue) {
diff --git a/native/android/looper.cpp b/native/android/looper.cpp
index 1564c47..0aeed77 100644
--- a/native/android/looper.cpp
+++ b/native/android/looper.cpp
@@ -72,9 +72,9 @@
     static_cast<PollLoop*>(looper)->decStrong((void*)ALooper_acquire);
 }
 
-void ALooper_addFd(ALooper* looper, int fd, int events,
+void ALooper_addFd(ALooper* looper, int fd, int ident, int events,
         ALooper_callbackFunc* callback, void* data) {
-    static_cast<PollLoop*>(looper)->setLooperCallback(fd, events, callback, data);
+    static_cast<PollLoop*>(looper)->setLooperCallback(fd, ident, events, callback, data);
 }
 
 int32_t ALooper_removeFd(ALooper* looper, int fd) {
diff --git a/native/android/sensor.cpp b/native/android/sensor.cpp
index db534e0..cf7635d 100644
--- a/native/android/sensor.cpp
+++ b/native/android/sensor.cpp
@@ -60,12 +60,12 @@
 }
 
 ASensorEventQueue* ASensorManager_createEventQueue(ASensorManager* manager,
-        ALooper* looper, ALooper_callbackFunc* callback, void* data)
+        ALooper* looper, int ident, ALooper_callbackFunc* callback, void* data)
 {
     sp<SensorEventQueue> queue =
             static_cast<SensorManager*>(manager)->createEventQueue();
     if (queue != 0) {
-        ALooper_addFd(looper, queue->getFd(), POLLIN, callback, data);
+        ALooper_addFd(looper, queue->getFd(), ident, POLLIN, callback, data);
         queue->looper = looper;
         queue->incStrong(manager);
     }
diff --git a/native/include/android/input.h b/native/include/android/input.h
index 418f609..9da122b 100644
--- a/native/include/android/input.h
+++ b/native/include/android/input.h
@@ -247,6 +247,22 @@
 };
 
 /*
+ * Motion event flags.
+ */
+enum {
+    /* This flag indicates that the window that received this motion event is partly
+     * or wholly obscured by another visible window above it.  This flag is set to true
+     * even if the event did not directly pass through the obscured area.
+     * A security sensitive application can check this flag to identify situations in which
+     * a malicious application may have covered up part of its content for the purpose
+     * of misleading the user or hijacking touches.  An appropriate response might be
+     * to drop the suspect touches or to take additional precautions to confirm the user's
+     * actual intent.
+     */
+    AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED = 0x1,
+};
+
+/*
  * Motion event edge touch flags.
  */
 enum {
@@ -395,6 +411,9 @@
 /* Get the combined motion event action code and pointer index. */
 int32_t AMotionEvent_getAction(const AInputEvent* motion_event);
 
+/* Get the motion event flags. */
+int32_t AMotionEvent_getFlags(const AInputEvent* motion_event);
+
 /* Get the state of any meta / modifier keys that were in effect when the
  * event was generated. */
 int32_t AMotionEvent_getMetaState(const AInputEvent* motion_event);
@@ -623,10 +642,10 @@
 
 /*
  * Add this input queue to a looper for processing.  See
- * ALooper_addFd() for information on the callback and data params.
+ * ALooper_addFd() for information on the ident, callback, and data params.
  */
 void AInputQueue_attachLooper(AInputQueue* queue, ALooper* looper,
-        ALooper_callbackFunc* callback, void* data);
+        int ident, ALooper_callbackFunc* callback, void* data);
 
 /*
  * Remove the input queue from the looper it is currently attached to.
diff --git a/native/include/android/looper.h b/native/include/android/looper.h
index 2917216..287bcd5 100644
--- a/native/include/android/looper.h
+++ b/native/include/android/looper.h
@@ -111,7 +111,7 @@
  *
  * Returns ALOPER_POLL_ERROR if an error occurred.
  *
- * Returns a value >= 0 containing a file descriptor if it has data
+ * Returns a value >= 0 containing an identifier if its file descriptor has data
  * and it has no callback function (requiring the caller here to handle it).
  * In this (and only this) case outEvents and outData will contain the poll
  * events and data associated with the fd.
@@ -145,10 +145,12 @@
  * descriptor was previously added, it is replaced.
  *
  * "fd" is the file descriptor to be added.
+ * "ident" is an identifier for this event, which is returned from
+ * ALooper_pollOnce().  Must be >= 0, or ALOOPER_POLL_CALLBACK if
+ * providing a non-NULL callback.
  * "events" are the poll events to wake up on.  Typically this is POLLIN.
  * "callback" is the function to call when there is an event on the file
  * descriptor.
- * "id" is an identifier to associated with this file descriptor, or 0.
  * "data" is a private data pointer to supply to the callback.
  *
  * There are two main uses of this function:
@@ -156,13 +158,13 @@
  * (1) If "callback" is non-NULL, then
  * this function will be called when there is data on the file descriptor.  It
  * should execute any events it has pending, appropriately reading from the
- * file descriptor.
+ * file descriptor.  The 'ident' is ignored in this case.
  *
- * (2) If "callback" is NULL, the fd will be returned by ALooper_pollOnce
- * when it has data available, requiring the caller to take care of processing
- * it.
+ * (2) If "callback" is NULL, the 'ident' will be returned by ALooper_pollOnce
+ * when its file descriptor has data available, requiring the caller to take
+ * care of processing it.
  */
-void ALooper_addFd(ALooper* looper, int fd, int events,
+void ALooper_addFd(ALooper* looper, int fd, int ident, int events,
         ALooper_callbackFunc* callback, void* data);
 
 /**
diff --git a/native/include/android/sensor.h b/native/include/android/sensor.h
index b4ce024..a102d43 100644
--- a/native/include/android/sensor.h
+++ b/native/include/android/sensor.h
@@ -166,7 +166,7 @@
  * Creates a new sensor event queue and associate it with a looper.
  */
 ASensorEventQueue* ASensorManager_createEventQueue(ASensorManager* manager,
-        ALooper* looper, ALooper_callbackFunc* callback, void* data);
+        ALooper* looper, int ident, ALooper_callbackFunc* callback, void* data);
 
 /*
  * Destroys the event queue and free all resources associated to it.
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index c81da70..f1f31cf 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -29,7 +29,7 @@
                 android:excludeFromRecents="true">
         </activity>
 
-        <activity android:name=".statusbar.RecentApplicationsActivity"
+        <activity android:name=".recent.RecentApplicationsActivity"
             android:theme="@android:style/Theme.NoTitleBar"
             android:excludeFromRecents="true"
             android:exported="true">
diff --git a/core/res/res/layout/recent_apps_activity.xml b/packages/SystemUI/res/layout/recent_apps_activity.xml
similarity index 87%
rename from core/res/res/layout/recent_apps_activity.xml
rename to packages/SystemUI/res/layout/recent_apps_activity.xml
index 45a200e..ec661e8 100644
--- a/core/res/res/layout/recent_apps_activity.xml
+++ b/packages/SystemUI/res/layout/recent_apps_activity.xml
@@ -32,7 +32,7 @@
         android:textColor="#80FFFFFF"
         android:textStyle="bold"
         android:singleLine="true"
-        android:text="@android:string/recent_tasks_title"
+        android:text="@string/recent_tasks_title"
         android:visibility="gone"/>
 
     <!-- This is only intended to be visible when carousel is invisible -->
@@ -42,14 +42,14 @@
         android:layout_height="wrap_content"
         android:layout_gravity="center"
         android:textAppearance="?android:attr/textAppearanceSmall"
-        android:text="@android:string/no_recent_tasks"
+        android:text="@string/recent_tasks_empty"
         android:visibility="gone"/>
 
-    <com.android.systemui.statusbar.RecentApplicationsCarouselView
+    <com.android.systemui.recent.RecentApplicationsCarouselView
         android:id="@+id/carousel"
         android:layout_width="match_parent"
         android:layout_height="0dip"
         android:layout_weight="1">
-    </com.android.systemui.statusbar.RecentApplicationsCarouselView>
+    </com.android.systemui.recent.RecentApplicationsCarouselView>
 
 </LinearLayout>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 2df3b6d..037dc4a 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -54,4 +54,17 @@
     <!-- Name of the button that links to the Settings app. [MAXCHARS=NONE] -->
     <string name="system_panel_settings_button">Settings</string>
 
+
+    <!-- Recent Tasks dialog: title
+     TODO: this should move to SystemUI.apk, but the code for the old 
+            recent dialog is still in the framework
+     -->
+    <string name="recent_tasks_title">Recent</string>
+    <!-- Recent Tasks dialog: message when there are no recent applications
+     TODO: this should move to SystemUI.apk, but the code for the old 
+            recent dialog is still in the framework
+     -->
+    <string name="recent_tasks_empty">No recent applications.</string>
+
+    
 </resources>
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/RecentApplicationsActivity.java b/packages/SystemUI/src/com/android/systemui/recent/RecentApplicationsActivity.java
similarity index 99%
rename from packages/SystemUI/src/com/android/systemui/statusbar/RecentApplicationsActivity.java
rename to packages/SystemUI/src/com/android/systemui/recent/RecentApplicationsActivity.java
index 6e5d241..6838dda 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/RecentApplicationsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentApplicationsActivity.java
@@ -15,11 +15,12 @@
  */
 
 
-package com.android.systemui.statusbar;
+package com.android.systemui.recent;
+
+import com.android.systemui.R;
 
 import com.android.ex.carousel.CarouselView;
 import com.android.ex.carousel.CarouselRS.CarouselCallback;
-import com.android.internal.R;
 
 import java.util.ArrayList;
 import java.util.List;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/RecentApplicationsCarouselView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentApplicationsCarouselView.java
similarity index 96%
rename from packages/SystemUI/src/com/android/systemui/statusbar/RecentApplicationsCarouselView.java
rename to packages/SystemUI/src/com/android/systemui/recent/RecentApplicationsCarouselView.java
index f5fcb11..1c8ec95 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/RecentApplicationsCarouselView.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentApplicationsCarouselView.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.systemui.statusbar;
+package com.android.systemui.recent;
 
 import android.content.Context;
 import android.util.AttributeSet;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarService.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarService.java
index 5dc46d0..6f74924 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarService.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarService.java
@@ -16,13 +16,9 @@
 
 package com.android.systemui.statusbar.tablet;
 
-import android.animation.Animator;
 import android.app.ActivityManagerNative;
-import android.app.Notification;
 import android.app.PendingIntent;
-import android.app.Service;
 import android.app.StatusBarManager;
-import android.content.ActivityNotFoundException;
 import android.content.Context;
 import android.content.Intent;
 import android.content.res.Resources;
@@ -33,7 +29,6 @@
 import android.os.Message;
 import android.os.RemoteException;
 import android.util.Slog;
-import android.view.animation.Animation;
 import android.view.animation.AnimationUtils;
 import android.view.Gravity;
 import android.view.LayoutInflater;
@@ -41,7 +36,6 @@
 import android.view.ViewGroup;
 import android.view.WindowManager;
 import android.view.WindowManagerImpl;
-import android.widget.Button;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
 import android.widget.RemoteViews;
@@ -50,10 +44,10 @@
 import android.widget.TextView;
 
 import com.android.internal.statusbar.StatusBarIcon;
-import com.android.internal.statusbar.StatusBarIconList;
 import com.android.internal.statusbar.StatusBarNotification;
 
 import com.android.systemui.statusbar.*;
+import com.android.systemui.recent.RecentApplicationsActivity;
 import com.android.systemui.R;
 
 public class TabletStatusBarService extends StatusBarService {
diff --git a/services/java/com/android/server/DeviceStorageMonitorService.java b/services/java/com/android/server/DeviceStorageMonitorService.java
index 4a0df59..0b1a4a3 100644
--- a/services/java/com/android/server/DeviceStorageMonitorService.java
+++ b/services/java/com/android/server/DeviceStorageMonitorService.java
@@ -69,10 +69,12 @@
     private static final int DEFAULT_FREE_STORAGE_LOG_INTERVAL_IN_MINUTES = 12*60; //in minutes
     private static final long DEFAULT_DISK_FREE_CHANGE_REPORTING_THRESHOLD = 2 * 1024 * 1024; // 2MB
     private static final long DEFAULT_CHECK_INTERVAL = MONITOR_INTERVAL*60*1000;
+    private static final int DEFAULT_FULL_THRESHOLD_BYTES = 1024*1024; // 1MB
     private long mFreeMem;  // on /data
     private long mLastReportedFreeMem;
     private long mLastReportedFreeMemTime;
     private boolean mLowMemFlag=false;
+    private boolean mMemFullFlag=false;
     private Context mContext;
     private ContentResolver mContentResolver;
     private long mTotalMemory;  // on /data
@@ -87,9 +89,13 @@
     private boolean mClearingCache;
     private Intent mStorageLowIntent;
     private Intent mStorageOkIntent;
+    private Intent mStorageFullIntent;
+    private Intent mStorageNotFullIntent;
     private CachePackageDataObserver mClearCacheObserver;
     private static final int _TRUE = 1;
     private static final int _FALSE = 0;
+    private long mMemLowThreshold;
+    private int mMemFullThreshold;
 
     /**
      * This string is used for ServiceManager access to this class.
@@ -103,7 +109,7 @@
     Handler mHandler = new Handler() {
         @Override
         public void handleMessage(Message msg) {
-            //dont handle an invalid message
+            //don't handle an invalid message
             if (msg.what != DEVICE_MEMORY_WHAT) {
                 Slog.e(TAG, "Will not process invalid message");
                 return;
@@ -184,7 +190,7 @@
         try {
             if (localLOGV) Slog.i(TAG, "Clearing cache");
             IPackageManager.Stub.asInterface(ServiceManager.getService("package")).
-                    freeStorageAndNotify(getMemThreshold(), mClearCacheObserver);
+                    freeStorageAndNotify(mMemLowThreshold, mClearCacheObserver);
         } catch (RemoteException e) {
             Slog.w(TAG, "Failed to get handle for PackageManger Exception: "+e);
             mClearingCache = false;
@@ -209,8 +215,7 @@
             if (localLOGV)  Slog.v(TAG, "freeMemory="+mFreeMem);
 
             //post intent to NotificationManager to display icon if necessary
-            long memThreshold = getMemThreshold();
-            if (mFreeMem < memThreshold) {
+            if (mFreeMem < mMemLowThreshold) {
                 if (!mLowMemFlag) {
                     if (checkCache) {
                         // See if clearing cache helps
@@ -235,6 +240,17 @@
                     mLowMemFlag = false;
                 }
             }
+            if (mFreeMem < mMemFullThreshold) {
+                if (!mMemFullFlag) {
+                    sendFullNotification();
+                    mMemFullFlag = true;
+                }
+            } else {
+                if (mMemFullFlag) {
+                    cancelFullNotification();
+                    mMemFullFlag = false;
+                }
+            }
         }
         if(localLOGV) Slog.i(TAG, "Posting Message again");
         //keep posting messages to itself periodically
@@ -264,6 +280,20 @@
         return mTotalMemory*value;
     }
 
+    /*
+     * just query settings to retrieve the memory full threshold.
+     * Preferred this over using a ContentObserver since Settings.Secure caches the value
+     * any way
+     */
+    private int getMemFullThreshold() {
+        int value = Settings.Secure.getInt(
+                              mContentResolver,
+                              Settings.Secure.SYS_STORAGE_FULL_THRESHOLD_BYTES,
+                              DEFAULT_FULL_THRESHOLD_BYTES);
+        if(localLOGV) Slog.v(TAG, "Full Threshold Bytes="+value);
+        return value;
+    }
+
     /**
     * Constructor to run service. initializes the disk space threshold value
     * and posts an empty message to kickstart the process.
@@ -283,6 +313,13 @@
         mStorageLowIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
         mStorageOkIntent = new Intent(Intent.ACTION_DEVICE_STORAGE_OK);
         mStorageOkIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+        mStorageFullIntent = new Intent(Intent.ACTION_DEVICE_STORAGE_FULL);
+        mStorageFullIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+        mStorageNotFullIntent = new Intent(Intent.ACTION_DEVICE_STORAGE_NOT_FULL);
+        mStorageNotFullIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+        // cache storage thresholds
+        mMemLowThreshold = getMemThreshold();
+        mMemFullThreshold = getMemFullThreshold();
         checkMemory(true);
     }
 
@@ -332,6 +369,23 @@
         mContext.sendBroadcast(mStorageOkIntent);
     }
 
+    /**
+     * Send a notification when storage is full.
+     */
+    private final void sendFullNotification() {
+        if(localLOGV) Slog.i(TAG, "Sending memory full notification");
+        mContext.sendStickyBroadcast(mStorageFullIntent);
+    }
+
+    /**
+     * Cancels memory full notification and sends "not full" intent.
+     */
+    private final void cancelFullNotification() {
+        if(localLOGV) Slog.i(TAG, "Canceling memory full notification");
+        mContext.removeStickyBroadcast(mStorageFullIntent);
+        mContext.sendBroadcast(mStorageNotFullIntent);
+    }
+
     public void updateMemory() {
         int callingUid = getCallingUid();
         if(callingUid != Process.SYSTEM_UID) {
diff --git a/services/java/com/android/server/InputWindow.java b/services/java/com/android/server/InputWindow.java
index 8da0cf1..dbc59ef 100644
--- a/services/java/com/android/server/InputWindow.java
+++ b/services/java/com/android/server/InputWindow.java
@@ -34,9 +34,17 @@
     // Dispatching timeout.
     public long dispatchingTimeoutNanos;
     
-    // Window frame position.
+    // Window frame area.
     public int frameLeft;
     public int frameTop;
+    public int frameRight;
+    public int frameBottom;
+    
+    // Window visible frame area.
+    public int visibleFrameLeft;
+    public int visibleFrameTop;
+    public int visibleFrameRight;
+    public int visibleFrameBottom;
     
     // Window touchable area.
     public int touchableAreaLeft;
diff --git a/services/java/com/android/server/ShutdownActivity.java b/services/java/com/android/server/ShutdownActivity.java
index 64b9c5d..c9d4d01 100644
--- a/services/java/com/android/server/ShutdownActivity.java
+++ b/services/java/com/android/server/ShutdownActivity.java
@@ -27,19 +27,26 @@
 public class ShutdownActivity extends Activity {
 
     private static final String TAG = "ShutdownActivity";
+    private boolean mReboot;
     private boolean mConfirm;
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
 
-        mConfirm = getIntent().getBooleanExtra(Intent.EXTRA_KEY_CONFIRM, false);
+        Intent intent = getIntent();
+        mReboot = Intent.ACTION_REBOOT.equals(intent.getAction());
+        mConfirm = intent.getBooleanExtra(Intent.EXTRA_KEY_CONFIRM, false);
         Slog.i(TAG, "onCreate(): confirm=" + mConfirm);
 
         Handler h = new Handler();
         h.post(new Runnable() {
             public void run() {
-                ShutdownThread.shutdown(ShutdownActivity.this, mConfirm);
+                if (mReboot) {
+                    ShutdownThread.reboot(ShutdownActivity.this, null, mConfirm);
+                } else {
+                    ShutdownThread.shutdown(ShutdownActivity.this, mConfirm);
+                }
             }
         });
     }
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java
index 79bde7c..2ab8091 100644
--- a/services/java/com/android/server/WindowManagerService.java
+++ b/services/java/com/android/server/WindowManagerService.java
@@ -5208,6 +5208,14 @@
                 final Rect frame = child.mFrame;
                 inputWindow.frameLeft = frame.left;
                 inputWindow.frameTop = frame.top;
+                inputWindow.frameRight = frame.right;
+                inputWindow.frameBottom = frame.bottom;
+                
+                final Rect visibleFrame = child.mVisibleFrame;
+                inputWindow.visibleFrameLeft = visibleFrame.left;
+                inputWindow.visibleFrameTop = visibleFrame.top;
+                inputWindow.visibleFrameRight = visibleFrame.right;
+                inputWindow.visibleFrameBottom = visibleFrame.bottom;
                 
                 switch (child.mTouchableInsets) {
                     default:
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 2ce8c08..7d8c307 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -132,7 +132,8 @@
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicLong;
 
-public final class ActivityManagerService extends ActivityManagerNative implements Watchdog.Monitor {
+public final class ActivityManagerService extends ActivityManagerNative
+        implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
     static final String TAG = "ActivityManager";
     static final boolean DEBUG = false;
     static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV;
@@ -751,6 +752,7 @@
     boolean mBooting = false;
     boolean mWaitingUpdate = false;
     boolean mDidUpdate = false;
+    boolean mOnBattery = false;
 
     Context mContext;
 
@@ -1382,8 +1384,10 @@
                 systemDir, "batterystats.bin").toString());
         mBatteryStatsService.getActiveStatistics().readLocked();
         mBatteryStatsService.getActiveStatistics().writeLocked();
+        mOnBattery = mBatteryStatsService.getActiveStatistics().getIsOnBattery();
+        mBatteryStatsService.getActiveStatistics().setCallback(this);
         
-        mUsageStatsService = new UsageStatsService( new File(
+        mUsageStatsService = new UsageStatsService(new File(
                 systemDir, "usagestats").toString());
 
         GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
@@ -1496,25 +1500,36 @@
             synchronized(bstats) {
                 synchronized(mPidsSelfLocked) {
                     if (haveNewCpuStats) {
-                        if (mBatteryStatsService.isOnBattery()) {
+                        if (mOnBattery) {
+                            int perc = bstats.startAddingCpuLocked();
+                            int totalUTime = 0;
+                            int totalSTime = 0;
                             final int N = mProcessStats.countWorkingStats();
                             for (int i=0; i<N; i++) {
                                 ProcessStats.Stats st
                                         = mProcessStats.getWorkingStats(i);
                                 ProcessRecord pr = mPidsSelfLocked.get(st.pid);
+                                int otherUTime = (st.rel_utime*perc)/100;
+                                int otherSTime = (st.rel_stime*perc)/100;
+                                totalUTime += otherUTime;
+                                totalSTime += otherSTime;
                                 if (pr != null) {
                                     BatteryStatsImpl.Uid.Proc ps = pr.batteryStats;
-                                    ps.addCpuTimeLocked(st.rel_utime, st.rel_stime);
+                                    ps.addCpuTimeLocked(st.rel_utime-otherUTime,
+                                            st.rel_stime-otherSTime);
                                     ps.addSpeedStepTimes(cpuSpeedTimes);
                                 } else {
                                     BatteryStatsImpl.Uid.Proc ps =
                                             bstats.getProcessStatsLocked(st.name, st.pid);
                                     if (ps != null) {
-                                        ps.addCpuTimeLocked(st.rel_utime, st.rel_stime);
+                                        ps.addCpuTimeLocked(st.rel_utime-otherUTime,
+                                                st.rel_stime-otherSTime);
                                         ps.addSpeedStepTimes(cpuSpeedTimes);
                                     }
                                 }
                             }
+                            bstats.finishAddingCpuLocked(perc, totalUTime,
+                                    totalSTime, cpuSpeedTimes);
                         }
                     }
                 }
@@ -1527,6 +1542,23 @@
         }
     }
     
+    @Override
+    public void batteryNeedsCpuUpdate() {
+        updateCpuStatsNow();
+    }
+
+    @Override
+    public void batteryPowerChanged(boolean onBattery) {
+        // When plugging in, update the CPU stats first before changing
+        // the plug state.
+        updateCpuStatsNow();
+        synchronized (this) {
+            synchronized(mPidsSelfLocked) {
+                mOnBattery = onBattery;
+            }
+        }
+    }
+
     /**
      * Initialize the application bind args. These are passed to each
      * process when the bindApplication() IPC is sent to the process. They're
diff --git a/services/java/com/android/server/am/ProcessRecord.java b/services/java/com/android/server/am/ProcessRecord.java
index 6d1fbab..67df707 100644
--- a/services/java/com/android/server/am/ProcessRecord.java
+++ b/services/java/com/android/server/am/ProcessRecord.java
@@ -131,6 +131,13 @@
     void dump(PrintWriter pw, String prefix) {
         final long now = SystemClock.uptimeMillis();
 
+        long wtime;
+        synchronized (batteryStats.getBatteryStats()) {
+            wtime = batteryStats.getBatteryStats().getProcessWakeTime(info.uid,
+                    pid, SystemClock.elapsedRealtime());
+        }
+        long timeUsed = wtime - lastWakeTime;
+
         if (info.className != null) {
             pw.print(prefix); pw.print("class="); pw.println(info.className);
         }
@@ -182,7 +189,9 @@
         pw.print(prefix); pw.print("adjSeq="); pw.print(adjSeq);
                 pw.print(" lruSeq="); pw.println(lruSeq);
         pw.print(prefix); pw.print("lastWakeTime="); pw.print(lastWakeTime);
-                pw.print(" lastRequestedGc=");
+                pw.print(" time used=");
+                TimeUtils.formatDuration(timeUsed, pw); pw.println("");
+        pw.print(prefix); pw.print("lastRequestedGc=");
                 TimeUtils.formatDuration(lastRequestedGc, now, pw);
                 pw.print(" lastLowMemory=");
                 TimeUtils.formatDuration(lastLowMemory, now, pw);
diff --git a/services/java/com/android/server/sip/SipSessionGroup.java b/services/java/com/android/server/sip/SipSessionGroup.java
index 8019bfa..70ff9ea 100644
--- a/services/java/com/android/server/sip/SipSessionGroup.java
+++ b/services/java/com/android/server/sip/SipSessionGroup.java
@@ -123,6 +123,7 @@
         properties.setProperty("javax.sip.STACK_NAME", getStackName());
         String outboundProxy = myself.getProxyAddress();
         if (!TextUtils.isEmpty(outboundProxy)) {
+            Log.v(TAG, "outboundProxy is " + outboundProxy);
             properties.setProperty("javax.sip.OUTBOUND_PROXY", outboundProxy
                     + ":" + myself.getPort() + "/" + myself.getProtocol());
         }
diff --git a/services/jni/com_android_server_InputManager.cpp b/services/jni/com_android_server_InputManager.cpp
index a237ee9..7af5e95 100644
--- a/services/jni/com_android_server_InputManager.cpp
+++ b/services/jni/com_android_server_InputManager.cpp
@@ -169,6 +169,12 @@
     jfieldID dispatchingTimeoutNanos;
     jfieldID frameLeft;
     jfieldID frameTop;
+    jfieldID frameRight;
+    jfieldID frameBottom;
+    jfieldID visibleFrameLeft;
+    jfieldID visibleFrameTop;
+    jfieldID visibleFrameRight;
+    jfieldID visibleFrameBottom;
     jfieldID touchableAreaLeft;
     jfieldID touchableAreaTop;
     jfieldID touchableAreaRight;
@@ -269,6 +275,7 @@
             nsecs_t& outNewTimeout);
     virtual void notifyInputChannelRecoveredFromANR(const sp<InputChannel>& inputChannel);
     virtual nsecs_t getKeyRepeatTimeout();
+    virtual nsecs_t getKeyRepeatDelay();
     virtual int32_t waitForKeyEventTargets(KeyEvent* keyEvent, uint32_t policyFlags,
             int32_t injectorPid, int32_t injectorUid, Vector<InputTarget>& outTargets);
     virtual int32_t waitForMotionEventTargets(MotionEvent* motionEvent, uint32_t policyFlags,
@@ -283,6 +290,12 @@
         nsecs_t dispatchingTimeout;
         int32_t frameLeft;
         int32_t frameTop;
+        int32_t frameRight;
+        int32_t frameBottom;
+        int32_t visibleFrameLeft;
+        int32_t visibleFrameTop;
+        int32_t visibleFrameRight;
+        int32_t visibleFrameBottom;
         int32_t touchableAreaLeft;
         int32_t touchableAreaTop;
         int32_t touchableAreaRight;
@@ -294,10 +307,8 @@
         int32_t ownerPid;
         int32_t ownerUid;
 
-        inline bool touchableAreaContainsPoint(int32_t x, int32_t y) {
-            return x >= touchableAreaLeft && x <= touchableAreaRight
-                    && y >= touchableAreaTop && y <= touchableAreaBottom;
-        }
+        bool visibleFrameIntersects(const InputWindow* other) const;
+        bool touchableAreaContainsPoint(int32_t x, int32_t y) const;
     };
 
     struct InputApplication {
@@ -370,9 +381,13 @@
     // Focus tracking for touch.
     bool mTouchDown;
     InputWindow* mTouchedWindow;                   // primary target for current down
+    bool mTouchedWindowIsObscured;                 // true if other windows may obscure the target
     Vector<InputWindow*> mTouchedWallpaperWindows; // wallpaper targets
-
-    Vector<InputWindow*> mTempTouchedOutsideWindows; // temporary outside touch targets
+    struct OutsideTarget {
+        InputWindow* window;
+        bool obscured;
+    };
+    Vector<OutsideTarget> mTempTouchedOutsideTargets; // temporary outside touch targets
     Vector<sp<InputChannel> > mTempTouchedWallpaperChannels; // temporary wallpaper targets
 
     // Focused application.
@@ -391,6 +406,7 @@
     int32_t waitForTouchedWindowLd(MotionEvent* motionEvent, uint32_t policyFlags,
             int32_t injectorPid, int32_t injectorUid,
             Vector<InputTarget>& outTargets, InputWindow*& outTouchedWindow);
+    bool isWindowObscuredLocked(const InputWindow* window);
 
     void releaseTouchedWindowLd();
 
@@ -996,6 +1012,10 @@
     }
 }
 
+nsecs_t NativeInputManager::getKeyRepeatDelay() {
+    return milliseconds_to_nanoseconds(50);
+}
+
 int32_t NativeInputManager::getMaxEventsPerSecond() {
     if (mMaxEventsPerSecond < 0) {
         JNIEnv* env = jniEnv();
@@ -1117,6 +1137,18 @@
                     gInputWindowClassInfo.frameLeft);
             jint frameTop = env->GetIntField(windowObj,
                     gInputWindowClassInfo.frameTop);
+            jint frameRight = env->GetIntField(windowObj,
+                    gInputWindowClassInfo.frameRight);
+            jint frameBottom = env->GetIntField(windowObj,
+                    gInputWindowClassInfo.frameBottom);
+            jint visibleFrameLeft = env->GetIntField(windowObj,
+                    gInputWindowClassInfo.visibleFrameLeft);
+            jint visibleFrameTop = env->GetIntField(windowObj,
+                    gInputWindowClassInfo.visibleFrameTop);
+            jint visibleFrameRight = env->GetIntField(windowObj,
+                    gInputWindowClassInfo.visibleFrameRight);
+            jint visibleFrameBottom = env->GetIntField(windowObj,
+                    gInputWindowClassInfo.visibleFrameBottom);
             jint touchableAreaLeft = env->GetIntField(windowObj,
                     gInputWindowClassInfo.touchableAreaLeft);
             jint touchableAreaTop = env->GetIntField(windowObj,
@@ -1144,6 +1176,12 @@
             outWindow.dispatchingTimeout = dispatchingTimeoutNanos;
             outWindow.frameLeft = frameLeft;
             outWindow.frameTop = frameTop;
+            outWindow.frameRight = frameRight;
+            outWindow.frameBottom = frameBottom;
+            outWindow.visibleFrameLeft = visibleFrameLeft;
+            outWindow.visibleFrameTop = visibleFrameTop;
+            outWindow.visibleFrameRight = visibleFrameRight;
+            outWindow.visibleFrameBottom = visibleFrameBottom;
             outWindow.touchableAreaLeft = touchableAreaLeft;
             outWindow.touchableAreaTop = touchableAreaTop;
             outWindow.touchableAreaRight = touchableAreaRight;
@@ -1417,11 +1455,12 @@
             /* Case 1: ACTION_DOWN */
 
             InputWindow* newTouchedWindow = NULL;
-            mTempTouchedOutsideWindows.clear();
+            mTempTouchedOutsideTargets.clear();
 
             int32_t x = int32_t(motionEvent->getX(0));
             int32_t y = int32_t(motionEvent->getY(0));
             InputWindow* topErrorWindow = NULL;
+            bool obscured = false;
 
             // Traverse windows from front to back to find touched window and outside targets.
             size_t numWindows = mWindows.size();
@@ -1442,13 +1481,17 @@
                         if (isTouchModal || window->touchableAreaContainsPoint(x, y)) {
                             if (! screenWasOff || flags & FLAG_TOUCHABLE_WHEN_WAKING) {
                                 newTouchedWindow = window;
+                                obscured = isWindowObscuredLocked(window);
                             }
                             break; // found touched window, exit window loop
                         }
                     }
 
                     if (flags & FLAG_WATCH_OUTSIDE_TOUCH) {
-                        mTempTouchedOutsideWindows.push(window);
+                        OutsideTarget outsideTarget;
+                        outsideTarget.window = window;
+                        outsideTarget.obscured = isWindowObscuredLocked(window);
+                        mTempTouchedOutsideTargets.push(outsideTarget);
                     }
                 }
             }
@@ -1501,6 +1544,7 @@
             releaseTouchedWindowLd();
 
             mTouchedWindow = newTouchedWindow;
+            mTouchedWindowIsObscured = obscured;
 
             if (newTouchedWindow->hasWallpaper) {
                 mTouchedWallpaperWindows.appendVector(mWallpaperWindows);
@@ -1557,21 +1601,31 @@
     if (injectionResult == INPUT_EVENT_INJECTION_SUCCEEDED) {
         size_t numWallpaperWindows = mTouchedWallpaperWindows.size();
         for (size_t i = 0; i < numWallpaperWindows; i++) {
-            addTarget(mTouchedWallpaperWindows[i], 0, 0, outTargets);
+            addTarget(mTouchedWallpaperWindows[i],
+                    InputTarget::FLAG_WINDOW_IS_OBSCURED, 0, outTargets);
         }
 
-        size_t numOutsideWindows = mTempTouchedOutsideWindows.size();
-        for (size_t i = 0; i < numOutsideWindows; i++) {
-            addTarget(mTempTouchedOutsideWindows[i], InputTarget::FLAG_OUTSIDE, 0, outTargets);
+        size_t numOutsideTargets = mTempTouchedOutsideTargets.size();
+        for (size_t i = 0; i < numOutsideTargets; i++) {
+            const OutsideTarget& outsideTarget = mTempTouchedOutsideTargets[i];
+            int32_t outsideTargetFlags = InputTarget::FLAG_OUTSIDE;
+            if (outsideTarget.obscured) {
+                outsideTargetFlags |= InputTarget::FLAG_WINDOW_IS_OBSCURED;
+            }
+            addTarget(outsideTarget.window, outsideTargetFlags, 0, outTargets);
         }
 
-        addTarget(mTouchedWindow, InputTarget::FLAG_SYNC,
+        int32_t targetFlags = InputTarget::FLAG_SYNC;
+        if (mTouchedWindowIsObscured) {
+            targetFlags |= InputTarget::FLAG_WINDOW_IS_OBSCURED;
+        }
+        addTarget(mTouchedWindow, targetFlags,
                 anrTimer.getTimeSpentWaitingForApplication(), outTargets);
         outTouchedWindow = mTouchedWindow;
     } else {
         outTouchedWindow = NULL;
     }
-    mTempTouchedOutsideWindows.clear();
+    mTempTouchedOutsideTargets.clear();
 
     // Check injection permission once and for all.
     if (injectionPermission == INJECTION_PERMISSION_UNKNOWN) {
@@ -1616,6 +1670,7 @@
 
 void NativeInputManager::releaseTouchedWindowLd() {
     mTouchedWindow = NULL;
+    mTouchedWindowIsObscured = false;
     mTouchedWallpaperWindows.clear();
 }
 
@@ -1661,6 +1716,20 @@
     return true;
 }
 
+bool NativeInputManager::isWindowObscuredLocked(const InputWindow* window) {
+    size_t numWindows = mWindows.size();
+    for (size_t i = 0; i < numWindows; i++) {
+        const InputWindow* other = & mWindows.itemAt(i);
+        if (other == window) {
+            break;
+        }
+        if (other->visible && window->visibleFrameIntersects(other)) {
+            return true;
+        }
+    }
+    return false;
+}
+
 int32_t NativeInputManager::waitForKeyEventTargets(KeyEvent* keyEvent, uint32_t policyFlags,
         int32_t injectorPid, int32_t injectorUid, Vector<InputTarget>& outTargets) {
 #if DEBUG_INPUT_DISPATCHER_POLICY
@@ -1935,12 +2004,17 @@
     for (size_t i = 0; i < mWindows.size(); i++) {
         dump.appendFormat("  windows[%d]: '%s', paused=%d, hasFocus=%d, hasWallpaper=%d, "
                 "visible=%d, flags=0x%08x, type=0x%08x, "
-                "frame=[%d,%d], touchableArea=[%d,%d][%d,%d], "
+                "frame=[%d,%d][%d,%d], "
+                "visibleFrame=[%d,%d][%d,%d], "
+                "touchableArea=[%d,%d][%d,%d], "
                 "ownerPid=%d, ownerUid=%d, dispatchingTimeout=%0.3fms\n",
                 i, mWindows[i].inputChannel->getName().string(),
                 mWindows[i].paused, mWindows[i].hasFocus, mWindows[i].hasWallpaper,
                 mWindows[i].visible, mWindows[i].layoutParamsFlags, mWindows[i].layoutParamsType,
                 mWindows[i].frameLeft, mWindows[i].frameTop,
+                mWindows[i].frameRight, mWindows[i].frameBottom,
+                mWindows[i].visibleFrameLeft, mWindows[i].visibleFrameTop,
+                mWindows[i].visibleFrameRight, mWindows[i].visibleFrameBottom,
                 mWindows[i].touchableAreaLeft, mWindows[i].touchableAreaTop,
                 mWindows[i].touchableAreaRight, mWindows[i].touchableAreaBottom,
                 mWindows[i].ownerPid, mWindows[i].ownerUid,
@@ -1955,6 +2029,20 @@
 
 // ----------------------------------------------------------------------------
 
+bool NativeInputManager::InputWindow::visibleFrameIntersects(const InputWindow* other) const {
+    return visibleFrameRight > other->visibleFrameLeft
+        && visibleFrameLeft < other->visibleFrameRight
+        && visibleFrameBottom > other->visibleFrameTop
+        && visibleFrameTop < other->visibleFrameBottom;
+}
+
+bool NativeInputManager::InputWindow::touchableAreaContainsPoint(int32_t x, int32_t y) const {
+    return x >= touchableAreaLeft && x <= touchableAreaRight
+            && y >= touchableAreaTop && y <= touchableAreaBottom;
+}
+
+// ----------------------------------------------------------------------------
+
 NativeInputManager::ANRTimer::ANRTimer() :
         mBudget(APPLICATION), mStartTime(now()), mFrozen(false), mPausedWindow(NULL) {
 }
@@ -2507,6 +2595,24 @@
     GET_FIELD_ID(gInputWindowClassInfo.frameTop, gInputWindowClassInfo.clazz,
             "frameTop", "I");
 
+    GET_FIELD_ID(gInputWindowClassInfo.frameRight, gInputWindowClassInfo.clazz,
+            "frameRight", "I");
+
+    GET_FIELD_ID(gInputWindowClassInfo.frameBottom, gInputWindowClassInfo.clazz,
+            "frameBottom", "I");
+
+    GET_FIELD_ID(gInputWindowClassInfo.visibleFrameLeft, gInputWindowClassInfo.clazz,
+            "visibleFrameLeft", "I");
+
+    GET_FIELD_ID(gInputWindowClassInfo.visibleFrameTop, gInputWindowClassInfo.clazz,
+            "visibleFrameTop", "I");
+
+    GET_FIELD_ID(gInputWindowClassInfo.visibleFrameRight, gInputWindowClassInfo.clazz,
+            "visibleFrameRight", "I");
+
+    GET_FIELD_ID(gInputWindowClassInfo.visibleFrameBottom, gInputWindowClassInfo.clazz,
+            "visibleFrameBottom", "I");
+
     GET_FIELD_ID(gInputWindowClassInfo.touchableAreaLeft, gInputWindowClassInfo.clazz,
             "touchableAreaLeft", "I");
 
diff --git a/telephony/java/android/telephony/PhoneNumberUtils.java b/telephony/java/android/telephony/PhoneNumberUtils.java
index 4f2d90f..e37733c 100644
--- a/telephony/java/android/telephony/PhoneNumberUtils.java
+++ b/telephony/java/android/telephony/PhoneNumberUtils.java
@@ -141,7 +141,7 @@
         Uri uri = intent.getData();
         String scheme = uri.getScheme();
 
-        if (scheme.equals("tel")) {
+        if (scheme.equals("tel") || scheme.equals("sip")) {
             return uri.getSchemeSpecificPart();
         }
 
diff --git a/telephony/java/com/android/internal/telephony/RIL.java b/telephony/java/com/android/internal/telephony/RIL.java
index 1a0dd89..8c2280b 100644
--- a/telephony/java/com/android/internal/telephony/RIL.java
+++ b/telephony/java/com/android/internal/telephony/RIL.java
@@ -1298,10 +1298,18 @@
     public void
     setupDataCall(String radioTechnology, String profile, String apn,
             String user, String password, String authType, Message result) {
+        setupDataCallWithProtocol(radioTechnology, profile, apn, user, password,
+                              authType, "IP", result);
+    }
+
+    public void
+    setupDataCallWithProtocol(String radioTechnology, String profile,
+            String apn, String user, String password, String authType,
+            String protocolType, Message result) {
         RILRequest rr
                 = RILRequest.obtain(RIL_REQUEST_SETUP_DATA_CALL, result);
 
-        rr.mp.writeInt(6);
+        rr.mp.writeInt(7);
 
         rr.mp.writeString(radioTechnology);
         rr.mp.writeString(profile);
@@ -1309,11 +1317,12 @@
         rr.mp.writeString(user);
         rr.mp.writeString(password);
         rr.mp.writeString(authType);
+        rr.mp.writeString(protocolType);
 
         if (RILJ_LOGD) riljLog(rr.serialString() + "> "
                 + requestToString(rr.mRequest) + " " + radioTechnology + " "
                 + profile + " " + apn + " " + user + " "
-                + password + " " + authType);
+                + password + " " + authType + " " + protocolType);
 
         send(rr);
     }
@@ -2901,7 +2910,11 @@
             dataCall.active = p.readInt();
             dataCall.type = p.readString();
             dataCall.apn = p.readString();
-            dataCall.address = p.readString();
+            String address = p.readString();
+            if (address != null) {
+                address = address.split(" ")[0];
+            }
+            dataCall.address = address;
 
             response.add(dataCall);
         }
diff --git a/telephony/java/com/android/internal/telephony/SMSDispatcher.java b/telephony/java/com/android/internal/telephony/SMSDispatcher.java
index f1a7107..3a7ce47 100644
--- a/telephony/java/com/android/internal/telephony/SMSDispatcher.java
+++ b/telephony/java/com/android/internal/telephony/SMSDispatcher.java
@@ -32,9 +32,11 @@
 import android.database.SQLException;
 import android.net.Uri;
 import android.os.AsyncResult;
+import android.os.Environment;
 import android.os.Handler;
 import android.os.Message;
 import android.os.PowerManager;
+import android.os.StatFs;
 import android.provider.Telephony;
 import android.provider.Telephony.Sms.Intents;
 import android.provider.Settings;
@@ -240,11 +242,9 @@
 
         // Register for device storage intents.  Use these to notify the RIL
         // that storage for SMS is or is not available.
-        // TODO: Revisit this for a later release.  Storage reporting should
-        // rely more on application indication.
         IntentFilter filter = new IntentFilter();
-        filter.addAction(Intent.ACTION_DEVICE_STORAGE_LOW);
-        filter.addAction(Intent.ACTION_DEVICE_STORAGE_OK);
+        filter.addAction(Intent.ACTION_DEVICE_STORAGE_FULL);
+        filter.addAction(Intent.ACTION_DEVICE_STORAGE_NOT_FULL);
         mContext.registerReceiver(mResultReceiver, filter);
     }
 
@@ -966,10 +966,10 @@
     private BroadcastReceiver mResultReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
-            if (intent.getAction().equals(Intent.ACTION_DEVICE_STORAGE_LOW)) {
+            if (intent.getAction().equals(Intent.ACTION_DEVICE_STORAGE_FULL)) {
                 mStorageAvailable = false;
                 mCm.reportSmsMemoryStatus(false, obtainMessage(EVENT_REPORT_MEMORY_STATUS_DONE));
-            } else if (intent.getAction().equals(Intent.ACTION_DEVICE_STORAGE_OK)) {
+            } else if (intent.getAction().equals(Intent.ACTION_DEVICE_STORAGE_NOT_FULL)) {
                 mStorageAvailable = true;
                 mCm.reportSmsMemoryStatus(true, obtainMessage(EVENT_REPORT_MEMORY_STATUS_DONE));
             } else {
diff --git a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
index 47a170a..6e53ec5 100755
--- a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
@@ -101,7 +101,6 @@
     CdmaCallTracker mCT;
     CdmaSMSDispatcher mSMS;
     CdmaServiceStateTracker mSST;
-    RuimFileHandler mRuimFileHandler;
     RuimRecords mRuimRecords;
     RuimCard mRuimCard;
     ArrayList <CdmaMmiCode> mPendingMmis = new ArrayList<CdmaMmiCode>();
@@ -159,7 +158,7 @@
         mDataConnection = new CdmaDataConnectionTracker (this);
         mRuimCard = new RuimCard(this);
         mRuimPhoneBookInterfaceManager = new RuimPhoneBookInterfaceManager(this);
-        mRuimSmsInterfaceManager = new RuimSmsInterfaceManager(this);
+        mRuimSmsInterfaceManager = new RuimSmsInterfaceManager(this, mSMS);
         mSubInfo = new PhoneSubInfo(this);
         mEriManager = new EriManager(this, context, EriManager.ERI_FROM_XML);
         mCcatService = CatService.getInstance(mCM, mRuimRecords, mContext,
diff --git a/telephony/java/com/android/internal/telephony/cdma/RuimSmsInterfaceManager.java b/telephony/java/com/android/internal/telephony/cdma/RuimSmsInterfaceManager.java
index a9df375..d84b6ab 100644
--- a/telephony/java/com/android/internal/telephony/cdma/RuimSmsInterfaceManager.java
+++ b/telephony/java/com/android/internal/telephony/cdma/RuimSmsInterfaceManager.java
@@ -27,6 +27,7 @@
 import com.android.internal.telephony.IccSmsInterfaceManager;
 import com.android.internal.telephony.IccUtils;
 import com.android.internal.telephony.PhoneProxy;
+import com.android.internal.telephony.SMSDispatcher;
 import com.android.internal.telephony.SmsRawData;
 
 import java.util.ArrayList;
@@ -80,9 +81,9 @@
         }
     };
 
-    public RuimSmsInterfaceManager(CDMAPhone phone) {
+    public RuimSmsInterfaceManager(CDMAPhone phone, SMSDispatcher dispatcher) {
         super(phone);
-        mDispatcher = new CdmaSMSDispatcher(phone);
+        mDispatcher = dispatcher;
     }
 
     public void dispose() {
diff --git a/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java b/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java
index d64541b..30a6324 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java
@@ -117,10 +117,6 @@
     Thread debugPortThread;
     ServerSocket debugSocket;
 
-    private int mReportedRadioResets;
-    private int mReportedAttemptedConnects;
-    private int mReportedSuccessfulConnects;
-
     private String mImei;
     private String mImeiSv;
     private String mVmNumber;
@@ -151,7 +147,7 @@
         mSimCard = new SimCard(this);
         if (!unitTestMode) {
             mSimPhoneBookIntManager = new SimPhoneBookInterfaceManager(this);
-            mSimSmsIntManager = new SimSmsInterfaceManager(this);
+            mSimSmsIntManager = new SimSmsInterfaceManager(this, mSMS);
             mSubInfo = new PhoneSubInfo(this);
         }
         mStkService = CatService.getInstance(mCM, mSIMRecords, mContext,
diff --git a/telephony/java/com/android/internal/telephony/gsm/SimSmsInterfaceManager.java b/telephony/java/com/android/internal/telephony/gsm/SimSmsInterfaceManager.java
index f000d79..aab359f 100644
--- a/telephony/java/com/android/internal/telephony/gsm/SimSmsInterfaceManager.java
+++ b/telephony/java/com/android/internal/telephony/gsm/SimSmsInterfaceManager.java
@@ -25,6 +25,7 @@
 import com.android.internal.telephony.IccConstants;
 import com.android.internal.telephony.IccSmsInterfaceManager;
 import com.android.internal.telephony.IccUtils;
+import com.android.internal.telephony.SMSDispatcher;
 import com.android.internal.telephony.SmsRawData;
 
 import java.util.ArrayList;
@@ -78,9 +79,9 @@
         }
     };
 
-    public SimSmsInterfaceManager(GSMPhone phone) {
+    public SimSmsInterfaceManager(GSMPhone phone, SMSDispatcher dispatcher) {
         super(phone);
-        mDispatcher = new GsmSMSDispatcher(phone);
+        mDispatcher = dispatcher;
     }
 
     public void dispose() {
diff --git a/telephony/java/com/android/internal/telephony/sip/SipPhoneBase.java b/telephony/java/com/android/internal/telephony/sip/SipPhoneBase.java
index e742887..5f26af4 100755
--- a/telephony/java/com/android/internal/telephony/sip/SipPhoneBase.java
+++ b/telephony/java/com/android/internal/telephony/sip/SipPhoneBase.java
@@ -175,8 +175,7 @@
     }
 
     public int getPhoneType() {
-        // FIXME: add SIP phone type
-        return Phone.PHONE_TYPE_GSM;
+        return Phone.PHONE_TYPE_SIP;
     }
 
     public SignalStrength getSignalStrength() {
diff --git a/test-runner/src/android/test/ProviderTestCase2.java b/test-runner/src/android/test/ProviderTestCase2.java
index 64d11c5..2811b0d 100644
--- a/test-runner/src/android/test/ProviderTestCase2.java
+++ b/test-runner/src/android/test/ProviderTestCase2.java
@@ -74,7 +74,7 @@
     private IsolatedContext mProviderContext;
     private MockContentResolver mResolver;
 
-       private class MockContext2 extends MockContext {
+    private class MockContext2 extends MockContext {
 
         @Override
         public Resources getResources() {
@@ -87,6 +87,11 @@
             // one created through the regular Context
             return getContext().getDir("mockcontext2_" + name, mode);
         }
+
+        @Override
+        public Context getApplicationContext() {
+            return this;
+        }
     }
     /**
      * Constructor.
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java b/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java
index 4cff3de..65da210 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java
@@ -81,8 +81,10 @@
         // http://b/issue?id=2889595
         "ietestcenter/Javascript/15.4.4.15-3-29.html", // hangs the layout tests
         // http://b/issue?id=2889596
-        "ietestcenter/Javascript/15.4.4.15-3-8.html" // hangs the layout tests
+        "ietestcenter/Javascript/15.4.4.15-3-8.html", // hangs the layout tests
         // http://b/issue?id=2889598
+        "http/tests/xmlhttprequest/simple-cross-origin-progress-events.html", // runs webcore into bad state
+        // http://b/2982500
     };
 
     static void fillIgnoreResultList() {
diff --git a/tests/DumpRenderTree2/assets/run_apache2.py b/tests/DumpRenderTree2/assets/run_apache2.py
index 74ab850..5d1e66c 100755
--- a/tests/DumpRenderTree2/assets/run_apache2.py
+++ b/tests/DumpRenderTree2/assets/run_apache2.py
@@ -76,8 +76,8 @@
   directives += " -c \"Alias /LayoutTests " + layout_tests_path + "\""
   directives += " -c \"Alias /WebKitTools/DumpRenderTree/android " + \
     os.path.join(webkit_path, "WebKitTools", "DumpRenderTree", "android") + "\""
-  directives += " -c \"Alias /WEBKIT_MERGE_REVISION " + \
-    os.path.join(webkit_path, "WEBKIT_MERGE_REVISION") + "\""
+  directives += " -c \"Alias /ThirdPartyProject.prop " + \
+    os.path.join(webkit_path, "ThirdPartyProject.prop") + "\""
 
   # This directive is commented out in apache2-debian-httpd.conf for some reason
   # However, it is useful to browse through tests in the browser, so it's added here.
diff --git a/tests/DumpRenderTree2/src/com/android/dumprendertree2/Summarizer.java b/tests/DumpRenderTree2/src/com/android/dumprendertree2/Summarizer.java
index d18fb14..0efb78e 100644
--- a/tests/DumpRenderTree2/src/com/android/dumprendertree2/Summarizer.java
+++ b/tests/DumpRenderTree2/src/com/android/dumprendertree2/Summarizer.java
@@ -326,15 +326,14 @@
     private String getWebKitRevision() {
         URL url = null;
         try {
-            url = new URL(ForwarderManager.getHostSchemePort(false) + "WEBKIT_MERGE_REVISION");
+            url = new URL(ForwarderManager.getHostSchemePort(false) + "ThirdPartyProject.prop");
         } catch (MalformedURLException e) {
             assert false;
         }
 
-        String webkitMergeRevisionFileContents = new String(FsUtils.readDataFromUrl(url));
-        Matcher matcher =
-            Pattern.compile("http://svn.webkit.org/repository/webkit/trunk@([0-9]+)").matcher(
-                    webkitMergeRevisionFileContents);
+        String thirdPartyProjectContents = new String(FsUtils.readDataFromUrl(url));
+        Matcher matcher = Pattern.compile("^version=([0-9]+)", Pattern.MULTILINE).matcher(
+                thirdPartyProjectContents);
         if (matcher.find()) {
             return matcher.group(1);
         }
@@ -482,4 +481,4 @@
         }
         return url;
     }
-}
\ No newline at end of file
+}