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<android.animation.Animatable.AnimatableListener>"
+ return="java.util.ArrayList<android.animation.Animator.AnimatorListener>"
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<android.animation.Animator>"
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<android.animation.Animatable>"
- 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<android.view.View>"
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 — 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 — 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—including blind stupidity.</p>
-<p>—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>—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 — that is, not until you have a
-perfectly clear and unoptimized solution. </li>
-</ul>
-<p>—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 — 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>—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
+}