summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api/11.xml44
-rw-r--r--api/current.xml57
-rw-r--r--core/java/android/animation/ObjectAnimator.java91
-rw-r--r--core/java/android/app/IntentService.java13
-rw-r--r--core/java/android/appwidget/AppWidgetHost.java11
-rwxr-xr-xcore/java/android/content/res/Resources.java1
-rw-r--r--core/java/android/view/View.java7
-rwxr-xr-xcore/java/android/view/WindowOrientationListener.java11
-rw-r--r--core/java/android/widget/AdapterViewAnimator.java7
-rw-r--r--core/java/android/widget/ProgressBar.java4
-rw-r--r--core/java/android/widget/RemoteViewsAdapter.java9
-rw-r--r--core/java/android/widget/StackView.java77
-rw-r--r--core/java/com/android/internal/view/menu/ActionMenuItemView.java7
-rw-r--r--core/java/com/android/internal/view/menu/ActionMenuView.java22
-rw-r--r--core/java/com/android/internal/view/menu/ListMenuItemView.java11
-rw-r--r--core/java/com/android/internal/view/menu/MenuItemImpl.java1
-rw-r--r--core/java/com/android/internal/widget/ActionBarView.java2
-rw-r--r--core/res/res/drawable-hdpi/stat_notify_chat.pngbin3852 -> 1625 bytes
-rw-r--r--core/res/res/drawable-hdpi/stat_notify_email_generic.pngbin2488 -> 337 bytes
-rw-r--r--core/res/res/drawable-hdpi/stat_notify_gmail.pngbin2322 -> 345 bytes
-rw-r--r--core/res/res/drawable-mdpi/stat_notify_chat.pngbin2312 -> 589 bytes
-rw-r--r--core/res/res/drawable-mdpi/stat_notify_email_generic.pngbin1565 -> 388 bytes
-rw-r--r--core/res/res/drawable-mdpi/stat_notify_gmail.pngbin1531 -> 397 bytes
-rw-r--r--core/res/res/drawable-xlarge-hdpi/stat_notify_chat.pngbin0 -> 3852 bytes
-rw-r--r--core/res/res/drawable-xlarge-hdpi/stat_notify_disk_full.pngbin0 -> 3361 bytes
-rw-r--r--core/res/res/drawable-xlarge-hdpi/stat_notify_email_generic.pngbin0 -> 2488 bytes
-rw-r--r--core/res/res/drawable-xlarge-hdpi/stat_notify_error.pngbin0 -> 2877 bytes
-rw-r--r--core/res/res/drawable-xlarge-hdpi/stat_notify_gmail.pngbin0 -> 2322 bytes
-rw-r--r--core/res/res/drawable-xlarge-mdpi/stat_notify_chat.pngbin0 -> 2312 bytes
-rw-r--r--core/res/res/drawable-xlarge-mdpi/stat_notify_disk_full.pngbin0 -> 2039 bytes
-rw-r--r--core/res/res/drawable-xlarge-mdpi/stat_notify_email_generic.pngbin0 -> 1565 bytes
-rw-r--r--core/res/res/drawable-xlarge-mdpi/stat_notify_error.pngbin0 -> 1838 bytes
-rw-r--r--core/res/res/drawable-xlarge-mdpi/stat_notify_gmail.pngbin0 -> 1531 bytes
-rw-r--r--core/res/res/layout/action_menu_item_layout.xml7
-rw-r--r--core/res/res/layout/list_menu_item_icon.xml2
-rw-r--r--core/res/res/layout/popup_menu_item_layout.xml5
-rw-r--r--core/res/res/layout/volume_adjust.xml34
-rw-r--r--core/res/res/values-es-rUS-xlarge/strings.xml4
-rwxr-xr-xcore/res/res/values/attrs.xml2
-rw-r--r--core/res/res/values/ids.xml1
-rw-r--r--core/res/res/values/styles.xml9
-rw-r--r--docs/html/guide/topics/advanced/aidl.jd387
-rw-r--r--docs/html/guide/topics/fundamentals/bound-services.jd675
-rw-r--r--docs/html/guide/topics/fundamentals/services.jd860
-rw-r--r--docs/html/images/fundamentals/service_binding_tree_lifecycle.pngbin0 -> 69225 bytes
-rw-r--r--docs/html/images/service_lifecycle.pngbin59286 -> 75830 bytes
-rw-r--r--graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java2
-rw-r--r--graphics/java/android/graphics/drawable/BitmapDrawable.java2
-rw-r--r--graphics/java/android/graphics/drawable/ClipDrawable.java2
-rw-r--r--graphics/java/android/graphics/drawable/ColorDrawable.java2
-rw-r--r--graphics/java/android/graphics/drawable/DrawableContainer.java2
-rw-r--r--graphics/java/android/graphics/drawable/GradientDrawable.java2
-rw-r--r--graphics/java/android/graphics/drawable/InsetDrawable.java2
-rw-r--r--graphics/java/android/graphics/drawable/LayerDrawable.java2
-rw-r--r--graphics/java/android/graphics/drawable/NinePatchDrawable.java2
-rw-r--r--graphics/java/android/graphics/drawable/RotateDrawable.java2
-rw-r--r--graphics/java/android/graphics/drawable/ScaleDrawable.java2
-rw-r--r--graphics/java/android/graphics/drawable/ShapeDrawable.java2
-rw-r--r--graphics/java/android/renderscript/Program.java8
-rw-r--r--libs/hwui/DisplayListRenderer.cpp24
-rw-r--r--libs/hwui/DisplayListRenderer.h34
-rw-r--r--libs/hwui/ResourceCache.cpp10
-rw-r--r--libs/hwui/SkiaShader.cpp74
-rw-r--r--libs/hwui/SkiaShader.h41
-rw-r--r--packages/SystemUI/res/drawable-hdpi/ic_sysbar_ime_default.pngbin1165 -> 931 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0.pngbin1188 -> 453 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1.pngbin1545 -> 839 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_fully.pngbin1558 -> 837 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2.pngbin1746 -> 993 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_fully.pngbin1755 -> 943 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3.pngbin1832 -> 1134 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_fully.pngbin1833 -> 1100 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4.pngbin1890 -> 1051 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_fully.pngbin1890 -> 993 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/stat_sys_signal_flightmode.pngbin872 -> 775 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_0.pngbin4232 -> 583 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1.pngbin1331 -> 1007 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1_fully.pngbin1359 -> 982 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_2.pngbin4643 -> 1160 bytes
-rwxr-xr-xpackages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_2_fully.pngbin4708 -> 1075 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_3.pngbin4874 -> 1252 bytes
-rwxr-xr-xpackages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_3_fully.pngbin4948 -> 1146 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_4.pngbin5167 -> 1209 bytes
-rwxr-xr-xpackages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_4_fully.pngbin5146 -> 1048 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_default.pngbin1072 -> 3900 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime_default.pngbin897 -> 1914 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime_pressed.pngbin2692 -> 3458 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_pressed.pngbin2920 -> 4249 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_default.pngbin1076 -> 3991 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_pressed.pngbin2673 -> 4373 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/ic_sysbar_ime_default.pngbin633 -> 744 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent_default.pngbin407 -> 3140 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent_pressed.pngbin1912 -> 3658 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0.pngbin409 -> 406 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1.pngbin431 -> 627 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_fully.pngbin431 -> 610 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1x.pngbin234 -> 494 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2.pngbin458 -> 732 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_fully.pngbin458 -> 709 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3.pngbin450 -> 802 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_fully.pngbin450 -> 757 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3g.pngbin258 -> 548 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4.pngbin424 -> 795 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_fully.pngbin424 -> 734 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/stat_sys_signal_edge.pngbin237 -> 425 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/stat_sys_signal_flightmode.pngbin3103 -> 612 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/stat_sys_signal_gprs.pngbin234 -> 503 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/stat_sys_signal_hsdpa.pngbin234 -> 422 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/stat_sys_signal_roam.pngbin236 -> 446 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_0.pngbin554 -> 508 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_1.pngbin492 -> 745 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_1_fully.pngbin492 -> 723 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_2.pngbin554 -> 835 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_2_fully.pngbin554 -> 782 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_3.pngbin616 -> 884 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_3_fully.pngbin616 -> 805 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_4.pngbin497 -> 911 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_4_fully.pngbin497 -> 786 bytes
-rw-r--r--packages/SystemUI/res/layout-xlarge/status_bar_notification_row.xml2
-rw-r--r--policy/src/com/android/internal/policy/impl/GlobalActions.java4
-rwxr-xr-xpolicy/src/com/android/internal/policy/impl/PhoneWindowManager.java4
-rw-r--r--services/java/com/android/server/InputManager.java2
-rw-r--r--services/java/com/android/server/InputMethodManagerService.java86
-rw-r--r--services/java/com/android/server/SystemServer.java17
-rw-r--r--services/java/com/android/server/WindowManagerService.java43
-rwxr-xr-xservices/java/com/android/server/am/ActivityManagerService.java28
-rw-r--r--tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java1
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/BitmapFactory.java4
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/BitmapShader_Delegate.java4
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java10
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java4
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/LinearGradient_Delegate.java4
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/Matrix_Delegate.java2
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/NinePatch_Delegate.java6
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java10
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java2
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/PorterDuffXfermode_Delegate.java4
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/RadialGradient_Delegate.java4
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/Region_Delegate.java6
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/SweepGradient_Delegate.java4
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java4
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java8
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java33
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeInflater.java2
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeResources.java14
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeTypedArray.java61
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/GcSnapshot.java31
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java3
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java12
149 files changed, 2589 insertions, 406 deletions
diff --git a/api/11.xml b/api/11.xml
index 6ace7ec97913..34a7a5c41ec2 100644
--- a/api/11.xml
+++ b/api/11.xml
@@ -171131,50 +171131,6 @@
<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
</exception>
</method>
-<field name="MAX_CONSTANT"
- type="int"
- transient="false"
- volatile="false"
- value="8"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="MAX_INPUT"
- type="int"
- transient="false"
- volatile="false"
- value="8"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="MAX_OUTPUT"
- type="int"
- transient="false"
- volatile="false"
- value="8"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="MAX_TEXTURE"
- type="int"
- transient="false"
- volatile="false"
- value="8"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
</class>
<class name="Program.BaseProgramBuilder"
extends="java.lang.Object"
diff --git a/api/current.xml b/api/current.xml
index 22f5c7da6a23..86c47f589e53 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -38983,6 +38983,17 @@
visibility="public"
>
</method>
+<method name="clearViews"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</method>
<method name="createView"
return="android.appwidget.AppWidgetHostView"
abstract="false"
@@ -171159,50 +171170,6 @@
<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
</exception>
</method>
-<field name="MAX_CONSTANT"
- type="int"
- transient="false"
- volatile="false"
- value="8"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="MAX_INPUT"
- type="int"
- transient="false"
- volatile="false"
- value="8"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="MAX_OUTPUT"
- type="int"
- transient="false"
- volatile="false"
- value="8"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="MAX_TEXTURE"
- type="int"
- transient="false"
- volatile="false"
- value="8"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
</class>
<class name="Program.BaseProgramBuilder"
extends="java.lang.Object"
@@ -260264,7 +260231,7 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="arg0" type="T">
+<parameter name="t" type="T">
</parameter>
</method>
</interface>
diff --git a/core/java/android/animation/ObjectAnimator.java b/core/java/android/animation/ObjectAnimator.java
index 7f11871b0f74..3212cba76bbb 100644
--- a/core/java/android/animation/ObjectAnimator.java
+++ b/core/java/android/animation/ObjectAnimator.java
@@ -18,6 +18,7 @@ package android.animation;
import android.util.Log;
+import java.lang.ref.WeakReference;
import java.lang.reflect.Method;
import java.util.ArrayList;
@@ -28,6 +29,8 @@ import java.util.ArrayList;
* are then determined internally and the animation will call these functions as necessary to
* animate the property.
*
+ * <p class="note"><b>Note:</b> Instances of this class hold only a {@link WeakReference}
+ * to the target object.</p>
* @see #setPropertyName(String)
*
*/
@@ -35,7 +38,7 @@ public final class ObjectAnimator extends ValueAnimator {
private static final boolean DBG = false;
// The target object on which the property exists, set in the constructor
- private Object mTarget;
+ private WeakReference<Object> mTargetRef;
private String mPropertyName;
@@ -102,6 +105,9 @@ public final class ObjectAnimator extends ValueAnimator {
* @return Method the method associated with mPropertyName.
*/
private Method getPropertyFunction(String prefix, Class valueType) {
+ final Object target = mTargetRef == null ? null : mTargetRef.get();
+ if (target == null) return null;
+
// TODO: faster implementation...
Method returnVal = null;
String firstLetter = mPropertyName.substring(0, 1);
@@ -114,7 +120,7 @@ public final class ObjectAnimator extends ValueAnimator {
args[0] = valueType;
}
try {
- returnVal = mTarget.getClass().getMethod(setterName, args);
+ returnVal = target.getClass().getMethod(setterName, args);
} catch (NoSuchMethodException e) {
Log.e("ObjectAnimator",
"Couldn't find setter/getter for property " + mPropertyName + ": " + e);
@@ -134,13 +140,14 @@ public final class ObjectAnimator extends ValueAnimator {
* A constructor that takes a single property name and set of values. This constructor is
* used in the simple case of animating a single property.
*
- * @param target The object whose property is to be animated. This object should
- * have a public method on it called <code>setName()</code>, where <code>name</code> is
- * the value of the <code>propertyName</code> parameter.
+ * @param target The object whose property is to be animated. It will be weakly referenced
+ * from the newly-created ObjectAnimator. This object should have a public method on it called
+ * <code>setName()</code>, where <code>name</code> is the value of the <code>propertyName</code>
+ * parameter.
* @param propertyName The name of the property being animated.
*/
private ObjectAnimator(Object target, String propertyName) {
- mTarget = target;
+ mTargetRef = new WeakReference<Object>(target);
setPropertyName(propertyName);
}
@@ -152,9 +159,10 @@ public final class ObjectAnimator extends ValueAnimator {
* from the target object and property being animated). Therefore, there should typically
* be two or more values.
*
- * @param target The object whose property is to be animated. This object should
- * have a public method on it called <code>setName()</code>, where <code>name</code> is
- * the value of the <code>propertyName</code> parameter.
+ * @param target The object whose property is to be animated. It will be weakly referenced
+ * from the newly-created ObjectAnimator. This object should have a public method on it called
+ * <code>setName()</code>, where <code>name</code> is the value of the <code>propertyName</code>
+ * parameter.
* @param propertyName The name of the property being animated.
* @param values A set of values that the animation will animate between over time.
* @return A ValueAnimator object that is set up to animate between the given values.
@@ -173,9 +181,10 @@ public final class ObjectAnimator extends ValueAnimator {
* from the target object and property being animated). Therefore, there should typically
* be two or more values.
*
- * @param target The object whose property is to be animated. This object should
- * have a public method on it called <code>setName()</code>, where <code>name</code> is
- * the value of the <code>propertyName</code> parameter.
+ * @param target The object whose property is to be animated. It will be weakly referenced
+ * from the newly-created ObjectAnimator. This object should have a public method on it called
+ * <code>setName()</code>, where <code>name</code> is the value of the <code>propertyName</code>
+ * parameter.
* @param propertyName The name of the property being animated.
* @param values A set of values that the animation will animate between over time.
* @return A ValueAnimator object that is set up to animate between the given values.
@@ -192,10 +201,10 @@ public final class ObjectAnimator extends ValueAnimator {
* PropertyValuesHolder allows you to associate a set of animation values with a property
* name.
*
- * @param target The object whose property is to be animated. This object should
- * have public methods on it called <code>setName()</code>, where <code>name</code> is
- * the name of the property passed in as the <code>propertyName</code> parameter for
- * each of the PropertyValuesHolder objects.
+ * @param target The object whose property is to be animated. It will be weakly referenced
+ * from the newly-created ObjectAnimator. This object should have public methods on it called
+ * <code>setName()</code>, where <code>name</code> is the name of the property passed in as the
+ * <code>propertyName</code> parameter for each of the PropertyValuesHolder objects.
* @param propertyName The name of the property being animated.
* @param evaluator A TypeEvaluator that will be called on each animation frame to
* provide the ncessry interpolation between the Object values to derive the animated
@@ -218,10 +227,10 @@ public final class ObjectAnimator extends ValueAnimator {
* PropertyValuesHolder allows you to associate a set of animation values with a property
* name.
*
- * @param target The object whose property is to be animated. This object should
- * have public methods on it called <code>setName()</code>, where <code>name</code> is
- * the name of the property passed in as the <code>propertyName</code> parameter for
- * each of the PropertyValuesHolder objects.
+ * @param target The object whose property is to be animated. It will be weakly referenced
+ * from the newly-created ObjectAnimator. This object should have public methods on it called
+ * <code>setName()</code>, where <code>name</code> is the name of the property passed in as the
+ * <code>propertyName</code> parameter for each of the PropertyValuesHolder objects.
* @param values A set of PropertyValuesHolder objects whose values will be animated
* between over time.
* @return A ValueAnimator object that is set up to animate between the given values.
@@ -229,7 +238,7 @@ public final class ObjectAnimator extends ValueAnimator {
public static ObjectAnimator ofPropertyValuesHolder(Object target,
PropertyValuesHolder... values) {
ObjectAnimator anim = new ObjectAnimator();
- anim.mTarget = target;
+ anim.mTargetRef = new WeakReference<Object>(target);
anim.setValues(values);
return anim;
}
@@ -270,7 +279,8 @@ public final class ObjectAnimator extends ValueAnimator {
@Override
public void start() {
if (DBG) {
- Log.d("ObjectAnimator", "Anim target, duration" + mTarget + ", " + getDuration());
+ final Object target = mTargetRef == null ? null : mTargetRef.get();
+ Log.d("ObjectAnimator", "Anim target, duration" + target + ", " + getDuration());
for (int i = 0; i < mValues.length; ++i) {
PropertyValuesHolder pvh = mValues[i];
ArrayList<Keyframe> keyframes = pvh.mKeyframeSet.mKeyframes;
@@ -297,11 +307,14 @@ public final class ObjectAnimator extends ValueAnimator {
@Override
void initAnimation() {
if (!mInitialized) {
+ final Object target = mTargetRef == null ? null : mTargetRef.get();
+ if (target == null) return;
+
// mValueType may change due to setter/getter setup; do this before calling super.init(),
// which uses mValueType to set up the default type evaluator.
int numValues = mValues.length;
for (int i = 0; i < numValues; ++i) {
- mValues[i].setupSetterAndGetter(mTarget);
+ mValues[i].setupSetterAndGetter(target);
}
super.initAnimation();
}
@@ -326,22 +339,26 @@ public final class ObjectAnimator extends ValueAnimator {
/**
* The target object whose property will be animated by this animation
*
- * @return The object being animated
+ * @return The object being animated, or null if the object has been garbage collected.
*/
public Object getTarget() {
- return mTarget;
+ return mTargetRef == null ? null : mTargetRef.get();
}
/**
- * Sets the target object whose property will be animated by this animation
+ * Sets the target object whose property will be animated by this animation. The target
+ * will be weakly referenced from this object.
*
* @param target The object being animated
*/
@Override
public void setTarget(Object target) {
- if (mTarget != target) {
- mTarget = target;
- if (mTarget != null && target != null && mTarget.getClass() == target.getClass()) {
+ final Object currentTarget = mTargetRef == null ? null : mTargetRef.get();
+
+ if (currentTarget != target) {
+ mTargetRef = new WeakReference<Object>(target);
+ if (currentTarget != null && target != null
+ && currentTarget.getClass() == target.getClass()) {
return;
}
// New target type should cause re-initialization prior to starting
@@ -351,19 +368,25 @@ public final class ObjectAnimator extends ValueAnimator {
@Override
public void setupStartValues() {
+ final Object target = mTargetRef == null ? null : mTargetRef.get();
+ if (target == null) return;
+
initAnimation();
int numValues = mValues.length;
for (int i = 0; i < numValues; ++i) {
- mValues[i].setupStartValue(mTarget);
+ mValues[i].setupStartValue(target);
}
}
@Override
public void setupEndValues() {
+ final Object target = mTargetRef == null ? null : mTargetRef.get();
+ if (target == null) return;
+
initAnimation();
int numValues = mValues.length;
for (int i = 0; i < numValues; ++i) {
- mValues[i].setupEndValue(mTarget);
+ mValues[i].setupEndValue(target);
}
}
@@ -382,9 +405,13 @@ public final class ObjectAnimator extends ValueAnimator {
@Override
void animateValue(float fraction) {
super.animateValue(fraction);
+
+ final Object target = mTargetRef == null ? null : mTargetRef.get();
+ if (target == null) return;
+
int numValues = mValues.length;
for (int i = 0; i < numValues; ++i) {
- mValues[i].setAnimatedValue(mTarget);
+ mValues[i].setAnimatedValue(target);
}
}
diff --git a/core/java/android/app/IntentService.java b/core/java/android/app/IntentService.java
index 7c2d3a091d40..57a26959bc8c 100644
--- a/core/java/android/app/IntentService.java
+++ b/core/java/android/app/IntentService.java
@@ -113,6 +113,12 @@ public abstract class IntentService extends Service {
mServiceHandler.sendMessage(msg);
}
+ /**
+ * You should not override this method for your IntentService. Instead,
+ * override {@link #onHandleIntent}, which the system calls when the IntentService
+ * receives a start request.
+ * @see android.app.Service#onStartCommand
+ */
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
onStart(intent, startId);
@@ -124,6 +130,11 @@ public abstract class IntentService extends Service {
mServiceLooper.quit();
}
+ /**
+ * Unless you provide binding for your service, you don't need to implement this
+ * method, because the default implementation returns null.
+ * @see android.app.Service#onBind
+ */
@Override
public IBinder onBind(Intent intent) {
return null;
@@ -135,6 +146,8 @@ public abstract class IntentService extends Service {
* worker thread that runs independently from other application logic.
* So, if this code takes a long time, it will hold up other requests to
* the same IntentService, but it will not hold up anything else.
+ * When all requests have been handled, the IntentService stops itself,
+ * so you should not call {@link #stopSelf}.
*
* @param intent The value passed to {@link
* android.content.Context#startService(Intent)}.
diff --git a/core/java/android/appwidget/AppWidgetHost.java b/core/java/android/appwidget/AppWidgetHost.java
index 7730942e467a..983548403004 100644
--- a/core/java/android/appwidget/AppWidgetHost.java
+++ b/core/java/android/appwidget/AppWidgetHost.java
@@ -214,6 +214,10 @@ public class AppWidgetHost {
}
}
+ /**
+ * Create the AppWidgetHostView for the given widget.
+ * The AppWidgetHost retains a pointer to the newly-created View.
+ */
public final AppWidgetHostView createView(Context context, int appWidgetId,
AppWidgetProviderInfo appWidget) {
AppWidgetHostView view = onCreateView(context, appWidgetId, appWidget);
@@ -272,6 +276,13 @@ public class AppWidgetHost {
v.viewDataChanged(viewId);
}
}
+
+ /**
+ * Clear the list of Views that have been created by this AppWidgetHost.
+ */
+ protected void clearViews() {
+ mViews.clear();
+ }
}
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index e8bf29d3719e..b40a22648be1 100755
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -1476,7 +1476,6 @@ public class Resources {
}
}
}
- cache.clear();
}
/**
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index c4bd1dee7c9e..f05ef8c588cd 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -7580,6 +7580,13 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
mHardwareLayer.destroy();
mHardwareLayer = null;
}
+
+ if (mAttachInfo != null) {
+ mAttachInfo.mHandler.removeMessages(AttachInfo.INVALIDATE_MSG, this);
+ mAttachInfo.mHandler.removeMessages(AttachInfo.INVALIDATE_RECT_MSG, this);
+ }
+
+ mCurrentAnimation = null;
}
/**
diff --git a/core/java/android/view/WindowOrientationListener.java b/core/java/android/view/WindowOrientationListener.java
index 2a76e33f94fe..6095a64d634a 100755
--- a/core/java/android/view/WindowOrientationListener.java
+++ b/core/java/android/view/WindowOrientationListener.java
@@ -234,6 +234,14 @@ public abstract class WindowOrientationListener {
// high time constant.
private static final float MAX_DEVIATION_FROM_GRAVITY = 1.5f;
+ // Minimum acceleration considered, in m/s^2. Below this threshold sensor noise will have
+ // significant impact on the calculations and in case of the vector (0, 0, 0) there is no
+ // defined rotation or tilt at all. Low or zero readings can happen when space travelling
+ // or free falling, but more commonly when shaking or getting bad readings from the sensor.
+ // The accelerometer is turned off when not used and polling it too soon after it is
+ // turned on may result in (0, 0, 0).
+ private static final float MIN_ABS_ACCELERATION = 1.5f;
+
// Actual sampling period corresponding to SensorManager.SENSOR_DELAY_NORMAL. There's no
// way to get this information from SensorManager.
// Note the actual period is generally 3-30ms larger than this depending on the device, but
@@ -347,6 +355,9 @@ public abstract class WindowOrientationListener {
float deviation = Math.abs(magnitude - SensorManager.STANDARD_GRAVITY);
handleAccelerationDistrust(deviation);
+ if (magnitude < MIN_ABS_ACCELERATION) {
+ return; // Ignore tilt and orientation when (0, 0, 0) or low reading
+ }
// only filter tilt when we're accelerating
float alpha = 1;
diff --git a/core/java/android/widget/AdapterViewAnimator.java b/core/java/android/widget/AdapterViewAnimator.java
index ec8e93c88947..c27082f928f9 100644
--- a/core/java/android/widget/AdapterViewAnimator.java
+++ b/core/java/android/widget/AdapterViewAnimator.java
@@ -787,6 +787,7 @@ public abstract class AdapterViewAnimator extends AdapterView<Adapter>
// We do the former in case mAdapter is null, and hence setDisplayedChild won't
// set mWhichChild
mWhichChild = ss.whichChild;
+
setDisplayedChild(mWhichChild);
}
@@ -986,4 +987,10 @@ public abstract class AdapterViewAnimator extends AdapterView<Adapter>
public void willBeAdvancedByHost() {
}
+
+ @Override
+ protected void onDetachedFromWindow() {
+ mAdapter = null;
+ super.onDetachedFromWindow();
+ }
}
diff --git a/core/java/android/widget/ProgressBar.java b/core/java/android/widget/ProgressBar.java
index 5b143fe2dd91..ef4e4e0a18a9 100644
--- a/core/java/android/widget/ProgressBar.java
+++ b/core/java/android/widget/ProgressBar.java
@@ -1004,9 +1004,11 @@ public class ProgressBar extends View {
@Override
protected void onDetachedFromWindow() {
- super.onDetachedFromWindow();
if (mIndeterminate) {
stopAnimation();
}
+ // This should come after stopAnimation(), otherwise an invalidate message remains in the
+ // queue, which can prevent the entire view hierarchy from being GC'ed during a rotation
+ super.onDetachedFromWindow();
}
}
diff --git a/core/java/android/widget/RemoteViewsAdapter.java b/core/java/android/widget/RemoteViewsAdapter.java
index a7bff62935a9..df1f4bf12dce 100644
--- a/core/java/android/widget/RemoteViewsAdapter.java
+++ b/core/java/android/widget/RemoteViewsAdapter.java
@@ -152,6 +152,7 @@ public class RemoteViewsAdapter extends BaseAdapter {
if (callback != null) {
callback.onRemoteAdapterDisconnected();
}
+ adapter.mCache.reset();
}
public IRemoteViewsFactory getRemoteViewsFactory() {
@@ -657,11 +658,9 @@ public class RemoteViewsAdapter extends BaseAdapter {
try {
remoteViews = factory.getViewAt(position);
itemId = factory.getItemId(position);
- } catch (Exception e) {
- // Print the error
- Log.e(TAG, "Error in updateRemoteViews(" + position + "): " +
- e.getMessage());
- e.printStackTrace();
+ } catch (Throwable t) {
+ Log.e(TAG, "Error in updateRemoteViews(" + position + "): " + t.getMessage());
+ t.printStackTrace();
// Return early to prevent additional work in re-centering the view cache, and
// swapping from the loading view
diff --git a/core/java/android/widget/StackView.java b/core/java/android/widget/StackView.java
index 0476d28fffdf..264af71eb438 100644
--- a/core/java/android/widget/StackView.java
+++ b/core/java/android/widget/StackView.java
@@ -194,7 +194,21 @@ public class StackView extends AdapterViewAnimator {
/**
* Animate the views between different relative indexes within the {@link AdapterViewAnimator}
*/
- void animateViewForTransition(int fromIndex, int toIndex, View view) {
+ void animateViewForTransition(int fromIndex, int toIndex, final View view) {
+ ObjectAnimator alphaOa = null;
+ ObjectAnimator oldAlphaOa = null;
+
+ // If there is currently an alpha animation on this view, we need
+ // to know about it, and may need to cancel it so as not to interfere with
+ // a new alpha animation.
+ Object tag = view.getTag(com.android.internal.R.id.viewAlphaAnimation);
+ if (tag instanceof WeakReference<?>) {
+ Object obj = ((WeakReference<?>) tag).get();
+ if (obj instanceof ObjectAnimator) {
+ oldAlphaOa = (ObjectAnimator) obj;
+ }
+ }
+
if (fromIndex == -1 && toIndex == NUM_ACTIVE_VIEWS -1) {
// Fade item in
if (view.getAlpha() == 1) {
@@ -206,9 +220,12 @@ public class StackView extends AdapterViewAnimator {
view.setTranslationY(0);
view.setVisibility(VISIBLE);
- ObjectAnimator fadeIn = ObjectAnimator.ofFloat(view, "alpha", view.getAlpha(), 1.0f);
- fadeIn.setDuration(FADE_IN_ANIMATION_DURATION);
- fadeIn.start();
+ alphaOa = ObjectAnimator.ofFloat(view, "alpha", view.getAlpha(), 1.0f);
+ alphaOa.setDuration(FADE_IN_ANIMATION_DURATION);
+ if (oldAlphaOa != null) oldAlphaOa.cancel();
+ alphaOa.start();
+ view.setTagInternal(com.android.internal.R.id.viewAlphaAnimation,
+ new WeakReference<ObjectAnimator>(alphaOa));
} else if (fromIndex == 0 && toIndex == 1) {
// Slide item in
view.setVisibility(VISIBLE);
@@ -216,39 +233,45 @@ public class StackView extends AdapterViewAnimator {
int duration = Math.round(mStackSlider.getDurationForNeutralPosition(mYVelocity));
StackSlider animationSlider = new StackSlider(mStackSlider);
+ animationSlider.setView(view);
PropertyValuesHolder slideInY = PropertyValuesHolder.ofFloat("YProgress", 0.0f);
PropertyValuesHolder slideInX = PropertyValuesHolder.ofFloat("XProgress", 0.0f);
- ObjectAnimator pa = ObjectAnimator.ofPropertyValuesHolder(animationSlider,
+ ObjectAnimator slideIn = ObjectAnimator.ofPropertyValuesHolder(animationSlider,
slideInX, slideInY);
- pa.setDuration(duration);
- pa.setInterpolator(new LinearInterpolator());
- pa.start();
+ slideIn.setDuration(duration);
+ slideIn.setInterpolator(new LinearInterpolator());
+ slideIn.start();
} else if (fromIndex == 1 && toIndex == 0) {
// Slide item out
int duration = Math.round(mStackSlider.getDurationForOffscreenPosition(mYVelocity));
StackSlider animationSlider = new StackSlider(mStackSlider);
+ animationSlider.setView(view);
PropertyValuesHolder slideOutY = PropertyValuesHolder.ofFloat("YProgress", 1.0f);
PropertyValuesHolder slideOutX = PropertyValuesHolder.ofFloat("XProgress", 0.0f);
- ObjectAnimator pa = ObjectAnimator.ofPropertyValuesHolder(animationSlider,
+ ObjectAnimator slideOut = ObjectAnimator.ofPropertyValuesHolder(animationSlider,
slideOutX, slideOutY);
- pa.setDuration(duration);
- pa.setInterpolator(new LinearInterpolator());
- pa.start();
- } else if (fromIndex == -1 && toIndex == 0) {
+ slideOut.setDuration(duration);
+ slideOut.setInterpolator(new LinearInterpolator());
+ slideOut.start();
+ } else if (toIndex == 0) {
// Make sure this view that is "waiting in the wings" is invisible
view.setAlpha(0.0f);
view.setVisibility(INVISIBLE);
- LayoutParams lp = (LayoutParams) view.getLayoutParams();
- lp.setVerticalOffset(-mSlideAmount);
+ } else if (fromIndex == 0 && toIndex > 1) {
+ view.setVisibility(VISIBLE);
+ view.setAlpha(1.0f);
} else if (fromIndex == -1) {
view.setAlpha(1.0f);
view.setVisibility(VISIBLE);
} else if (toIndex == -1) {
// Fade item out
- ObjectAnimator fadeOut = ObjectAnimator.ofFloat(view, "alpha", view.getAlpha(), 0.0f);
- fadeOut.setDuration(STACK_RELAYOUT_DURATION);
- fadeOut.start();
+ alphaOa = ObjectAnimator.ofFloat(view, "alpha", view.getAlpha(), 0.0f);
+ alphaOa.setDuration(STACK_RELAYOUT_DURATION);
+ if (oldAlphaOa != null) oldAlphaOa.cancel();
+ alphaOa.start();
+ view.setTagInternal(com.android.internal.R.id.viewAlphaAnimation,
+ new WeakReference<ObjectAnimator>(alphaOa));
}
// Implement the faked perspective
@@ -279,6 +302,16 @@ public class StackView extends AdapterViewAnimator {
(getMeasuredWidth() * (1 - PERSPECTIVE_SHIFT_FACTOR_X) / 2.0f);
final float transX = perspectiveTranslationX + scaleShiftCorrectionX;
+ // If this view is currently being animated for a certain position, we need to cancel
+ // this animation so as not to interfere with the new transformation.
+ Object tag = view.getTag(com.android.internal.R.id.viewAnimation);
+ if (tag instanceof WeakReference<?>) {
+ Object obj = ((WeakReference<?>) tag).get();
+ if (obj instanceof ObjectAnimator) {
+ ((ObjectAnimator) obj).cancel();
+ }
+ }
+
if (animate) {
PropertyValuesHolder translationX = PropertyValuesHolder.ofFloat("translationX", transX);
PropertyValuesHolder translationY = PropertyValuesHolder.ofFloat("translationY", transY);
@@ -292,14 +325,6 @@ public class StackView extends AdapterViewAnimator {
new WeakReference<ObjectAnimator>(oa));
oa.start();
} else {
- Object tag = view.getTag(com.android.internal.R.id.viewAnimation);
- if (tag instanceof WeakReference<?>) {
- Object obj = ((WeakReference<?>) tag).get();
- if (obj instanceof ObjectAnimator) {
- ((ObjectAnimator) obj).cancel();
- }
- }
-
view.setTranslationX(transX);
view.setTranslationY(transY);
view.setScaleX(scale);
diff --git a/core/java/com/android/internal/view/menu/ActionMenuItemView.java b/core/java/com/android/internal/view/menu/ActionMenuItemView.java
index d5f69bab9fcd..3325df617de9 100644
--- a/core/java/com/android/internal/view/menu/ActionMenuItemView.java
+++ b/core/java/com/android/internal/view/menu/ActionMenuItemView.java
@@ -66,7 +66,7 @@ public class ActionMenuItemView extends LinearLayout
mItemData = itemData;
setIcon(itemData.getIcon());
- setTitle(itemData.getTitle()); // Title only takes effect if there is no icon
+ setTitle(itemData.getTitleForItemView(this)); // Title only takes effect if there is no icon
setId(itemData.getItemId());
setVisibility(itemData.isVisible() ? View.VISIBLE : View.GONE);
@@ -91,7 +91,7 @@ public class ActionMenuItemView extends LinearLayout
}
public boolean prefersCondensedTitle() {
- return false;
+ return true;
}
public void setCheckable(boolean checkable) {
@@ -106,10 +106,11 @@ public class ActionMenuItemView extends LinearLayout
mImageButton.setImageDrawable(icon);
if (icon != null) {
mImageButton.setVisibility(VISIBLE);
- mTextButton.setVisibility(GONE);
} else {
mImageButton.setVisibility(GONE);
}
+
+ mTextButton.setVisibility(icon == null || mItemData.showsTextAsAction() ? VISIBLE : GONE);
}
public boolean hasText() {
diff --git a/core/java/com/android/internal/view/menu/ActionMenuView.java b/core/java/com/android/internal/view/menu/ActionMenuView.java
index 463902fe53e9..8e491e9fdd62 100644
--- a/core/java/com/android/internal/view/menu/ActionMenuView.java
+++ b/core/java/com/android/internal/view/menu/ActionMenuView.java
@@ -20,9 +20,9 @@ import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
+import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.Gravity;
-import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;
@@ -186,10 +186,14 @@ public class ActionMenuView extends LinearLayout implements MenuBuilder.ItemInvo
boolean needsDivider = false;
for (int i = 0; i < itemCount; i++) {
+ final MenuItemImpl itemData = itemsToShow.get(i);
+ boolean hasDivider = false;
+
if (needsDivider) {
addView(makeDividerView(), makeDividerLayoutParams());
+ hasDivider = true;
}
- final MenuItemImpl itemData = itemsToShow.get(i);
+
View actionView = itemData.getActionView();
if (actionView != null) {
@@ -199,14 +203,22 @@ public class ActionMenuView extends LinearLayout implements MenuBuilder.ItemInvo
}
addView(actionView, makeActionViewLayoutParams(actionView));
} else {
- needsDivider = addItemView(i == 0 || !needsDivider,
- (ActionMenuItemView) itemData.getItemView(
- MenuBuilder.TYPE_ACTION_BUTTON, this));
+ ActionMenuItemView view = (ActionMenuItemView) itemData.getItemView(
+ MenuBuilder.TYPE_ACTION_BUTTON, this);
+ view.setItemInvoker(this);
+ if (i > 0 && !hasDivider && view.hasText() && itemData.getIcon() == null) {
+ addView(makeDividerView(), makeDividerLayoutParams());
+ }
+ addView(view);
+ needsDivider = view.hasText();
}
}
if (reserveOverflow) {
if (mMenu.getNonActionItems(true).size() > 0) {
+ if (itemCount > 0) {
+ addView(makeDividerView(), makeDividerLayoutParams());
+ }
OverflowMenuButton button = new OverflowMenuButton(mContext);
addView(button);
mOverflowButton = button;
diff --git a/core/java/com/android/internal/view/menu/ListMenuItemView.java b/core/java/com/android/internal/view/menu/ListMenuItemView.java
index e15587520625..02584b618cf2 100644
--- a/core/java/com/android/internal/view/menu/ListMenuItemView.java
+++ b/core/java/com/android/internal/view/menu/ListMenuItemView.java
@@ -44,6 +44,7 @@ public class ListMenuItemView extends LinearLayout implements MenuView.ItemView
private Drawable mBackground;
private int mTextAppearance;
private Context mTextAppearanceContext;
+ private boolean mPreserveIconSpacing;
private int mMenuType;
@@ -57,6 +58,8 @@ public class ListMenuItemView extends LinearLayout implements MenuView.ItemView
mBackground = a.getDrawable(com.android.internal.R.styleable.MenuView_itemBackground);
mTextAppearance = a.getResourceId(com.android.internal.R.styleable.
MenuView_itemTextAppearance, -1);
+ mPreserveIconSpacing = a.getBoolean(
+ com.android.internal.R.styleable.MenuView_preserveIconSpacing, false);
mTextAppearanceContext = context;
a.recycle();
@@ -184,8 +187,8 @@ public class ListMenuItemView extends LinearLayout implements MenuView.ItemView
}
public void setIcon(Drawable icon) {
-
- if (!mItemData.shouldShowIcon(mMenuType)) {
+ final boolean showIcon = mItemData.shouldShowIcon(mMenuType);
+ if (!showIcon && !mPreserveIconSpacing) {
return;
}
@@ -197,8 +200,8 @@ public class ListMenuItemView extends LinearLayout implements MenuView.ItemView
insertIconView();
}
- if (icon != null) {
- mIconView.setImageDrawable(icon);
+ if (icon != null || mPreserveIconSpacing) {
+ mIconView.setImageDrawable(showIcon ? icon : null);
if (mIconView.getVisibility() != VISIBLE) {
mIconView.setVisibility(VISIBLE);
diff --git a/core/java/com/android/internal/view/menu/MenuItemImpl.java b/core/java/com/android/internal/view/menu/MenuItemImpl.java
index e1aa385fa051..6fbae9446f30 100644
--- a/core/java/com/android/internal/view/menu/MenuItemImpl.java
+++ b/core/java/com/android/internal/view/menu/MenuItemImpl.java
@@ -644,7 +644,6 @@ public final class MenuItemImpl implements MenuItem {
public boolean shouldShowIcon(int menuType) {
return menuType == MenuBuilder.TYPE_ICON ||
menuType == MenuBuilder.TYPE_ACTION_BUTTON ||
- menuType == MenuBuilder.TYPE_POPUP ||
mMenu.getOptionalIconsVisible();
}
diff --git a/core/java/com/android/internal/widget/ActionBarView.java b/core/java/com/android/internal/widget/ActionBarView.java
index 1d9276a39daf..297dde78254b 100644
--- a/core/java/com/android/internal/widget/ActionBarView.java
+++ b/core/java/com/android/internal/widget/ActionBarView.java
@@ -437,7 +437,7 @@ public class ActionBarView extends ViewGroup {
mListNavLayout = new LinearLayout(mContext, null,
com.android.internal.R.attr.actionBarTabBarStyle);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
- LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
+ LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT);
params.gravity = Gravity.CENTER;
mListNavLayout.addView(mSpinner, params);
}
diff --git a/core/res/res/drawable-hdpi/stat_notify_chat.png b/core/res/res/drawable-hdpi/stat_notify_chat.png
index 95b2700f337c..71ea8de6b682 100644
--- a/core/res/res/drawable-hdpi/stat_notify_chat.png
+++ b/core/res/res/drawable-hdpi/stat_notify_chat.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_notify_email_generic.png b/core/res/res/drawable-hdpi/stat_notify_email_generic.png
index f222872886a9..bc5fcab3c365 100644
--- a/core/res/res/drawable-hdpi/stat_notify_email_generic.png
+++ b/core/res/res/drawable-hdpi/stat_notify_email_generic.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_notify_gmail.png b/core/res/res/drawable-hdpi/stat_notify_gmail.png
index 2d5686ddeef3..ea8beaee100a 100644
--- a/core/res/res/drawable-hdpi/stat_notify_gmail.png
+++ b/core/res/res/drawable-hdpi/stat_notify_gmail.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_notify_chat.png b/core/res/res/drawable-mdpi/stat_notify_chat.png
index f199fcea6ef9..306d9c561b6b 100644
--- a/core/res/res/drawable-mdpi/stat_notify_chat.png
+++ b/core/res/res/drawable-mdpi/stat_notify_chat.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_notify_email_generic.png b/core/res/res/drawable-mdpi/stat_notify_email_generic.png
index 536e8ec8818e..1620ad537eaf 100644
--- a/core/res/res/drawable-mdpi/stat_notify_email_generic.png
+++ b/core/res/res/drawable-mdpi/stat_notify_email_generic.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_notify_gmail.png b/core/res/res/drawable-mdpi/stat_notify_gmail.png
index 89fe3cd6daed..4860c3459ff6 100644
--- a/core/res/res/drawable-mdpi/stat_notify_gmail.png
+++ b/core/res/res/drawable-mdpi/stat_notify_gmail.png
Binary files differ
diff --git a/core/res/res/drawable-xlarge-hdpi/stat_notify_chat.png b/core/res/res/drawable-xlarge-hdpi/stat_notify_chat.png
new file mode 100644
index 000000000000..e936faceda63
--- /dev/null
+++ b/core/res/res/drawable-xlarge-hdpi/stat_notify_chat.png
Binary files differ
diff --git a/core/res/res/drawable-xlarge-hdpi/stat_notify_disk_full.png b/core/res/res/drawable-xlarge-hdpi/stat_notify_disk_full.png
new file mode 100644
index 000000000000..eb626df39878
--- /dev/null
+++ b/core/res/res/drawable-xlarge-hdpi/stat_notify_disk_full.png
Binary files differ
diff --git a/core/res/res/drawable-xlarge-hdpi/stat_notify_email_generic.png b/core/res/res/drawable-xlarge-hdpi/stat_notify_email_generic.png
new file mode 100644
index 000000000000..d6bc7d30cddb
--- /dev/null
+++ b/core/res/res/drawable-xlarge-hdpi/stat_notify_email_generic.png
Binary files differ
diff --git a/core/res/res/drawable-xlarge-hdpi/stat_notify_error.png b/core/res/res/drawable-xlarge-hdpi/stat_notify_error.png
new file mode 100644
index 000000000000..8c8f25dbc171
--- /dev/null
+++ b/core/res/res/drawable-xlarge-hdpi/stat_notify_error.png
Binary files differ
diff --git a/core/res/res/drawable-xlarge-hdpi/stat_notify_gmail.png b/core/res/res/drawable-xlarge-hdpi/stat_notify_gmail.png
new file mode 100644
index 000000000000..661cc2ff47b8
--- /dev/null
+++ b/core/res/res/drawable-xlarge-hdpi/stat_notify_gmail.png
Binary files differ
diff --git a/core/res/res/drawable-xlarge-mdpi/stat_notify_chat.png b/core/res/res/drawable-xlarge-mdpi/stat_notify_chat.png
new file mode 100644
index 000000000000..b2d71862c8cc
--- /dev/null
+++ b/core/res/res/drawable-xlarge-mdpi/stat_notify_chat.png
Binary files differ
diff --git a/core/res/res/drawable-xlarge-mdpi/stat_notify_disk_full.png b/core/res/res/drawable-xlarge-mdpi/stat_notify_disk_full.png
new file mode 100644
index 000000000000..36ab1ff76f47
--- /dev/null
+++ b/core/res/res/drawable-xlarge-mdpi/stat_notify_disk_full.png
Binary files differ
diff --git a/core/res/res/drawable-xlarge-mdpi/stat_notify_email_generic.png b/core/res/res/drawable-xlarge-mdpi/stat_notify_email_generic.png
new file mode 100644
index 000000000000..a14b3c7d0e7c
--- /dev/null
+++ b/core/res/res/drawable-xlarge-mdpi/stat_notify_email_generic.png
Binary files differ
diff --git a/core/res/res/drawable-xlarge-mdpi/stat_notify_error.png b/core/res/res/drawable-xlarge-mdpi/stat_notify_error.png
new file mode 100644
index 000000000000..81a66c112876
--- /dev/null
+++ b/core/res/res/drawable-xlarge-mdpi/stat_notify_error.png
Binary files differ
diff --git a/core/res/res/drawable-xlarge-mdpi/stat_notify_gmail.png b/core/res/res/drawable-xlarge-mdpi/stat_notify_gmail.png
new file mode 100644
index 000000000000..a286ac611169
--- /dev/null
+++ b/core/res/res/drawable-xlarge-mdpi/stat_notify_gmail.png
Binary files differ
diff --git a/core/res/res/layout/action_menu_item_layout.xml b/core/res/res/layout/action_menu_item_layout.xml
index e502b1e6c03a..e0018945d7b4 100644
--- a/core/res/res/layout/action_menu_item_layout.xml
+++ b/core/res/res/layout/action_menu_item_layout.xml
@@ -20,10 +20,11 @@
android:layout_gravity="center"
android:addStatesFromChildren="true"
android:background="?attr/selectableItemBackground"
- android:minWidth="64dip"
- android:minHeight="?attr/actionBarSize"
+ android:gravity="center"
android:paddingLeft="12dip"
- android:paddingRight="12dip">
+ android:paddingRight="12dip"
+ android:minWidth="64dip"
+ android:minHeight="?attr/actionBarSize">
<ImageButton android:id="@+id/imageButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
diff --git a/core/res/res/layout/list_menu_item_icon.xml b/core/res/res/layout/list_menu_item_icon.xml
index 2be9fab3fc94..6ff14dd8b197 100644
--- a/core/res/res/layout/list_menu_item_icon.xml
+++ b/core/res/res/layout/list_menu_item_icon.xml
@@ -19,6 +19,6 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
- android:layout_marginLeft="2dip"
+ android:layout_marginRight="8dip"
android:duplicateParentState="true" />
diff --git a/core/res/res/layout/popup_menu_item_layout.xml b/core/res/res/layout/popup_menu_item_layout.xml
index 2bbb4d06baf1..d22f74a055b7 100644
--- a/core/res/res/layout/popup_menu_item_layout.xml
+++ b/core/res/res/layout/popup_menu_item_layout.xml
@@ -16,7 +16,8 @@
<com.android.internal.view.menu.ListMenuItemView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
- android:layout_height="?android:attr/listPreferredItemHeight"
+ android:layout_height="48dip"
+ android:minWidth="196dip"
android:paddingLeft="16dip"
android:paddingRight="16dip">
@@ -28,8 +29,6 @@
android:layout_weight="1"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
- android:layout_marginLeft="6dip"
- android:layout_marginRight="6dip"
android:duplicateParentState="true">
<TextView
diff --git a/core/res/res/layout/volume_adjust.xml b/core/res/res/layout/volume_adjust.xml
index c44ed0bf91df..18da85f93d9a 100644
--- a/core/res/res/layout/volume_adjust.xml
+++ b/core/res/res/layout/volume_adjust.xml
@@ -14,24 +14,32 @@
limitations under the License.
-->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:background="@android:drawable/toast_frame"
- android:orientation="vertical"
- android:gravity="center_horizontal">
+ android:background="@android:drawable/dialog_full_holo_dark"
+ android:gravity="left">
+
+ <LinearLayout
+ android:layout_width="416dip"
+ android:layout_height="wrap_content"
+ android:paddingLeft="16dip"
+ android:paddingTop="16dip"
+ android:paddingRight="16dip"
+ android:paddingBottom="8dip"
+ android:orientation="vertical">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_marginTop="14dip"
- android:gravity="center_vertical">
+ android:layout_marginBottom="8dip"
+ android:gravity="left">
<ImageView
android:id="@+id/other_stream_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_marginRight="6dip" />
+ android:layout_marginRight="16dip" />
<TextView
android:layout_width="wrap_content"
@@ -56,13 +64,9 @@
<ProgressBar
style="?android:attr/progressBarStyleHorizontal"
android:id="@+id/level"
- android:layout_width="200dip"
- android:layout_height="wrap_content"
- android:layout_marginTop="14dip"
- android:layout_marginBottom="14dip"
- android:layout_marginLeft="25dip"
- android:layout_marginRight="25dip" />
-
-</LinearLayout>
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" />
+ </LinearLayout>
+</FrameLayout>
diff --git a/core/res/res/values-es-rUS-xlarge/strings.xml b/core/res/res/values-es-rUS-xlarge/strings.xml
index 4743ac5daf1c..b1409baaf16c 100644
--- a/core/res/res/values-es-rUS-xlarge/strings.xml
+++ b/core/res/res/values-es-rUS-xlarge/strings.xml
@@ -303,6 +303,10 @@
<!-- XL -->
<string name="status_bar_notification_info_overflow" msgid="1081154808901480710">"100+"</string>
<!-- XL -->
+ <string name="permlab_accessMtp" msgid="2385215229145694622">"implementar protocolo MTP"</string>
+ <!-- XL -->
+ <string name="permdesc_accessMtp" msgid="4707854877711083465">"Permite acceso al driver kernel MTP para implementar el protocolo MTP USB."</string>
+ <!-- XL -->
<string name="permlab_mediaStorageWrite" product="default" msgid="5585262071354704256">"modificar/eliminar los contenidos del almacenamientos de medios internos"</string>
<!-- XL -->
<string name="permdesc_mediaStorageWrite" product="default" msgid="2372999661142345443">"Permite que una aplicación modifique los contenidos del almacenamiento interno de medios."</string>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index a29f4172c408..02855b5405ca 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -2349,6 +2349,8 @@
<attr name="windowAnimationStyle" />
<!-- Default disabled icon alpha for each menu item that shows an icon. -->
<attr name="itemIconDisabledAlpha" format="float" />
+ <!-- Whether space should be reserved in layout when an icon is missing. -->
+ <attr name="preserveIconSpacing" format="boolean" />
</declare-styleable>
<declare-styleable name="IconMenuView">
<!-- Defines the height of each row. -->
diff --git a/core/res/res/values/ids.xml b/core/res/res/values/ids.xml
index 93ccd4f9b8cd..837e04f536e8 100644
--- a/core/res/res/values/ids.xml
+++ b/core/res/res/values/ids.xml
@@ -74,4 +74,5 @@
<item type="id" name="rowTypeId" />
<item type="id" name="up" />
<item type="id" name="viewAnimation" />
+ <item type="id" name="viewAlphaAnimation" />
</resources>
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index cf9c00b2547d..1183915003d3 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -1194,7 +1194,7 @@
</style>
<style name="TextAppearance.Holo.Widget.PopupMenu.Large">
- <item name="android:textSize">22sp</item>
+ <item name="android:textSize">18sp</item>
</style>
<style name="TextAppearance.Holo.Widget.PopupMenu.Small">
@@ -1578,7 +1578,6 @@
</style>
<style name="Widget.Holo.Spinner.DropDown.ActionBar">
- <item name="android:background">@android:drawable/spinner_cab_background_holo_dark</item>
</style>
<style name="Widget.Holo.CompoundButton.Star" parent="Widget.CompoundButton.Star">
@@ -1651,6 +1650,8 @@
</style>
<style name="Widget.Holo.ActionButton" parent="Widget.ActionButton">
+ <item name="android:minWidth">64dip</item>
+ <item name="android:gravity">center</item>
<item name="android:paddingLeft">16dip</item>
<item name="android:paddingRight">16dip</item>
<item name="android:minHeight">56dip</item>
@@ -1677,9 +1678,6 @@
</style>
<style name="Widget.Holo.ActionBarView_TabBar" parent="Widget.ActionBarView_TabBar">
- <item name="divider">?android:attr/dividerVertical</item>
- <item name="showDividers">beginning|end</item>
- <item name="dividerPadding">8dip</item>
</style>
<style name="Widget.Holo.ActionBarView_TabText" parent="Widget.ActionBarView_TabText">
@@ -1920,7 +1918,6 @@
</style>
<style name="Widget.Holo.Light.Spinner.DropDown.ActionBar">
- <item name="android:background">@android:drawable/spinner_cab_background_holo_light</item>
</style>
<style name="Widget.Holo.Light.CompoundButton.Star" parent="Widget.CompoundButton.Star">
diff --git a/docs/html/guide/topics/advanced/aidl.jd b/docs/html/guide/topics/advanced/aidl.jd
new file mode 100644
index 000000000000..fef46eca464f
--- /dev/null
+++ b/docs/html/guide/topics/advanced/aidl.jd
@@ -0,0 +1,387 @@
+page.title=Android Interface Definition Language (AIDL)
+@jd:body
+
+
+
+<p>AIDL (Android Interface Definition Language) is similar to other IDLs you might have
+worked with. It allows you to define the programming interface that both
+the client and service agree upon in order to communicate with each other and allows for
+interprocess communication (IPC). On Android, one process can not normally access the
+memory of another process. So to talk, they need to decompose their objects into primitives that the
+operating system can understand, and "marshall" the object across that boundary for you. The code to
+do that marshalling is tedious to write, so Android handles it for you with AIDL.</p>
+
+<p class="note"><strong>Note:</strong> Using AIDL is necessary only if you allow clients from
+different applications to access your service for IPC and want to handle multithreading in your
+service. If you do not need to perform IPC across
+different applications, you should create your interface <a href="Binder">implementing a
+Binder</a> or, if you want to perform IPC, but do not need to handle multithreading, then you
+should implement your interface <a href="#Messenger">using a Messenger</a>.</p>
+
+<p>Before you begin designing your AIDL interface, be aware that calls on to an AIDL interface are
+direct function calls. You can not generally make assumptions about the thread in which the call
+will happen. What happens is different depending on whether the call is from a thread in the
+local process, or coming from a remote process. Specifically:</p>
+
+<ul>
+<li>Calls from the local process are executed in the same thread that is making the call. If this is
+your main UI thread, that thread will continue executing into the aidl interface. If it is another
+thread, that is one that will be executing your code. Thus if only local threads are accessing the
+interface, you can completely control which threads are executing in it (but if that is the case,
+why are you defining an aidl interface at all?).</li>
+
+<li>Calls from a remote process are dispatched from a thread pool the platform maintains inside of
+your own process. You must be prepared for incoming calls from unknown threads, with multiple calls
+happening at the same time. In other words, an implementation of an aidl interface must be
+completely thread-safe.</li>
+
+<li>The "oneway" keyword modifies the behavior of remote calls. When used, a remote call will not
+block until its call completes; it simply sends the transaction data and immediately returns. The
+implementation of the interface will eventually receive this as a regular call from the {@link
+android.os.Binder} thread pool as a normal remote call. If "oneway" is used with a local call,
+there is no impact and the call is still synchronous.</li>
+</ul>
+
+
+<h2 id="Defining">Defining an AIDL Interface</h2>
+
+<p>You must define your AIDL interface in an {@code .aidl} file using the Java
+programming language syntax, then save it in the source code (in the {@code src/} directory) of both
+the application hosting the service and any other application that will bind to the service.</p>
+
+<p>When you build the projects containing the {@code .aidl} file, the Android SDK tools generate an
+{@link android.os.IBinder} class based on your AIDL interface (and saves the file in the {@code
+gen/} directory). This class defines the APIs you can call to perform RPC as an interface&mdash;you
+must implement the interface in your service.</p>
+
+<p>To create a bounded service using AIDL, follow these steps:</p>
+<ol>
+ <li><a href="#CreateAidl">Create the .aidl file</a>
+ <p>This file defines the programming interface with method signatures.</p>
+ </li>
+ <li><a href="#ImplementTheInterface">Implement the interface</a>
+ <p>The Android SDK tools generate an interface in the Java programming language, based on your
+{@code .aidl} file. This interface has an inner abstract class named {@code Stub} that extends
+{@link android.os.Binder} and implements methods from your AIDL interface. You must extend the
+{@code Stub} class and implement the methods.</p>
+ </li>
+ <li><a href="#ExposeTheInterface">Expose the interface to clients</a>
+ <p>Implement a {@link android.app.Service Service} and override {@link
+android.app.Service#onBind onBind()} to return your implementation of the {@code Stub}
+class.</p>
+ </li>
+</ol>
+
+<p class="caution"><strong>Caution:</strong> Any changes that you make to your AIDL interface after
+your first release must remain backward compatible in order to avoid breaking other applications
+that use your service. That is, because your {@code .aidl} file must be copied to other applications
+in order for them to access your service's interface, you must maintain support for the original
+interface.</p>
+
+
+<h3 id="CreateAidl">1. Create the .aidl file</h3>
+
+<p>AIDL uses a simple syntax that lets you declare an interface with one or more methods that can
+take parameters and return values. The parameters and return values can be of any type, even other
+AIDL-generated interfaces.</p>
+
+<p>The syntax for the {@code .aidl} file uses the Java programming language. The file defines a
+single interface and requires only the interface declaration and method signatures.</p>
+
+<p>By default, AIDL supports the following data types:</p>
+
+<ul>
+ <li>All primitive types in the Java programming language ({@code int}, {@code long}, {@code
+char}, {@code boolean}, etc.)</li>
+ <li>{@link java.lang.String}</li>
+ <li>{@link java.lang.CharSequence}</li>
+ <li>{@link java.util.List}
+ <p>All elements in the {@link java.util.List} must be one of the supported data types in this
+list or one of the other AIDL-generated interfaces or parcelables you've declared. A {@link
+java.util.List} may optionally be used as a "generic" class (e.g. <code>List&lt;String&gt;</code>).
+The actual concrete class that the other side will receive will always be an {@link
+java.util.ArrayList}, although the method will be generated to use the {@link
+java.util.List} interface.</p>
+ </li>
+ <li>{@link java.util.Map}
+ <p>All elements in the {@link java.util.Map} must be one of the supported data types in this
+list or one of the other AIDL-generated interfaces or parcelables you've declared. Generic maps,
+(such as those of the form
+{@code Map&lt;String,Integer&gt;} are not supported. The actual concrete class that the other side
+will receive will always be a {@link java.util.HashMap}, although the method will be generated to
+use the {@link java.util.Map} interface.</p>
+ </li>
+</ul>
+
+<p>You must include an {@code import} statement for each additional type not listed above, even if
+they are defined in the same package as your interface.</p>
+
+<p>When defining methods for your service interface, be aware that:</p>
+<ul>
+ <li>Methods can take zero or more parameters, and return a value or void.</li>
+ <li>All non-primitive parameters require a directional tag indicating which way the data will go.
+Either <code>in</code>, <code>out</code>, or <code>inout</code> (see the example below).
+ <p>Primitives are <code>in</code> by default, and cannot be otherwise.</p>
+ <p class="caution"><strong>Caution:</strong> You should limit the direction to what is truly
+needed, because marshalling parameters is expensive.</p></li>
+ <li>All code comments included in the {@code .aidl} file are included in the generated {@link
+android.os.IBinder} interface (except for comments before the import and package
+statements).</li>
+</ul>
+
+<p>Here is an example {@code .aidl} file:</p>
+
+<pre>
+// IRemoteService.aidl
+package com.example.android;
+
+// Declare any non-default types here with import statements
+
+/** Example service interface */
+interface IRemoteService {
+ /** Request the process ID of this service, to do evil things with it. */
+ int getPid();
+
+ /** Demonstrates some basic types that you can use as parameters
+ * and return values in AIDL.
+ */
+ void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
+ double aDouble, String aString);
+}
+</pre>
+
+<p>Simply save your {@code .aidl} file in your project's {@code src/} directory and when you
+build your application, the SDK tools will generate the binder class file in your project's
+{@code gen/} directory. The generated file name matches the {@code .aidl} file name, but with a
+{@code .java} extension (for example, {@code IRemoteService.aidl} results in {@code
+IRemoteService.java}).</p>
+
+<p>If you use Eclipse, the incremental build generates the binder class almost immediately. If you
+do not use Eclipse, then the Ant tool generates the binder class next time you build your
+application&mdash;you should build your project with <code>ant debug</code> (or <code>ant
+release</code>) as soon as you're finished writing the {@code .aidl} file, so that your code can
+link against the generated class.</p>
+
+
+<h3 id="ImplementTheInterface">2. Implement the interface</h3>
+
+<p>When you build your application, the Android SDK tools generate a {@code .java} interface file
+named after your {@code .aidl} file. The generated interface includes a subclass named {@code Stub}
+that is an abstract implementation of its parent interface (for example, {@code
+YourInterface.Stub}) and declares all the methods from the {@code .aidl} file.</p>
+
+<p class="note"><strong>Note:</strong> {@code Stub} also
+defines a few helper methods, most notably {@code asInterface()}, which takes an {@link
+android.os.IBinder} (usually the one passed to a client's {@link
+android.content.ServiceConnection#onServiceConnected onServiceConnected()} callback method) and
+returns an instance of the stub interface. See the section <a href="#calling">Calling an IPC
+Method</a> for more details on how to make this cast.</p></p>
+
+<p>To implement the interface generated from the {@code .aidl}, extend the generated {@link
+android.os.Binder} interface (for example, {@code YourInterface.Stub}) and implement the methods
+inherited from the {@code .aidl} file.</p>
+
+<p>Here is an example implementation of an interface called {@code IRemoteService} (defined by the
+{@code IRemoteService.aidl} example, above) using an anonymous instance:</p>
+
+<pre>
+private final IRemoteService.Stub mBinder = new IRemoteService.Stub() {
+ public int getPid(){
+ return Process.myPid();
+ }
+ public void basicTypes(int anInt, long aLong, boolean aBoolean,
+ float aFloat, double aDouble, String aString) {
+ // Does nothing
+ }
+};
+</pre>
+
+<p>Now the {@code mBinder} is an instance of the {@code Stub} class (a {@link android.os.Binder}),
+which defines the RPC interface for the service. In the next step, this instance is exposed to
+clients so they can interact with the service.</p>
+
+<p>There are a few rules you should be aware of when implementing your AIDL interface: </p>
+<ul>
+ <li>Incoming calls are not guaranteed to be executed on the main thread, so you need to think
+about multithreading from the start and properly build your service to be thread-safe.</li>
+ <li>By default, RPC calls are synchronous. If you know that the service takes more than a few
+milliseconds to complete a request, you should not call it from the activity's main thread, because
+it might hang the application (Android might display an &quot;Application is Not Responding&quot;
+dialog)&mdash;you should usually call them from a separate thread in the client. </li>
+ <li>No exceptions that you throw are sent back to the caller.</li>
+ <li>Only methods are supported; you cannot expose static fields in AIDL.</li>
+</ul>
+
+
+<h3 id="ExposeTheInterface">3. Expose the interface to clients</h3>
+
+<p>Once you've implemented the interface for your service, you need to expose it to
+clients so they can bind to it. To expose the interface
+for your service, extend {@link android.app.Service Service} and implement {@link
+android.app.Service#onBind onBind()} to return an instance of your class that implements
+the generated {@code Stub} (as discussed in the previous section). Here's an example
+service that exposes the {@code IRemoteService} example interface to clients. </p>
+
+<pre>
+public class RemoteService extends Service {
+ &#64;Override
+ public void onCreate() {
+ super.onCreate();
+ }
+
+ &#64;Override
+ public IBinder onBind(Intent intent) {
+ // Return the interface
+ return mBinder;
+ }
+
+ private final IRemoteService.Stub mBinder = new IRemoteService.Stub() {
+ public int getPid(){
+ return Process.myPid();
+ }
+ public void basicTypes(int anInt, long aLong, boolean aBoolean,
+ float aFloat, double aDouble, String aString) {
+ // Does nothing
+ }
+ };
+}
+</pre>
+
+<p>Now, when a client (such as an activity) calls {@link android.content.Context#bindService
+bindService()} to connect to this service, the client's {@link
+android.content.ServiceConnection#onServiceConnected onServiceConnected()} callback receives the
+{@code mBinder} instance returned by the service's {@link android.app.Service#onBind onBind()}
+method.</p>
+
+<p>The client must also have access to the interface class, so if the client and service are in
+separate applications, then the client's application must have a copy of the {@code .aidl} file
+in its {@code src/} directory (which generates the {@code android.os.Binder}
+interface&mdash;providing the client access to the AIDL methods).</p>
+
+<p>When the client receives the {@link android.os.IBinder} in the {@link
+android.content.ServiceConnection#onServiceConnected onServiceConnected()} callback, it must call
+<code><em>YourServiceInterface</em>.Stub.asInterface(service)</code> to cast the returned
+parameter to <code><em>YourServiceInterface</em></code> type. For example:</p>
+
+<pre>
+IRemoteService mIRemoteService;
+private ServiceConnection mConnection = new ServiceConnection() {
+ // Called when the connection with the service is established
+ public void onServiceConnected(ComponentName className, IBinder service) {
+ // Following the example above for an AIDL interface,
+ // this gets an instance of the IRemoteInterface, which we can use to call on the service
+ mIRemoteService = IRemoteService.Stub.asInterface(service);
+ }
+
+ // Called when the connection with the service disconnects unexpectedly
+ public void onServiceDisconnected(ComponentName className) {
+ Log.e(TAG, "onServiceDisconnected");
+ }
+};
+</pre>
+
+<p>For more sample code, see the <a
+href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/RemoteService.html">{@code
+RemoteService.java}</a> class in <a
+href="{@docRoot}resources/samples/ApiDemos/index.html">ApiDemos</a>.</p>
+
+
+
+
+
+
+
+
+<h2 id="PassingObjects">Passing Objects over IPC</h2>
+
+<p>If you have a class that you would like to send from one process to another through
+an IPC interface, you can do that. However, you must ensure that the code for your class is
+available to the other side of the IPC and the class must support the {@link
+android.os.Parcelable} interface, in order for the objects to be decomposed into primitives and
+marshalled across processes by the Android system.</p>
+
+<p>There are five parts to making a class support the {@link android.os.Parcelable} protocol:</b>
+<ol>
+<li>Make your class implement the {@link android.os.Parcelable} interface.</li>
+<li>Implement {@link android.os.Parcelable#writeToParcel writeToParcel}, which takes the
+current state of the object and writes it to a {@link android.os.Parcel}.</li>
+<li>Add a static field called <code>CREATOR</code> to your class which is an object implementing
+the {@link android.os.Parcelable.Creator Parcelable.Creator} interface.</li>
+<li>Finally, create an {@code .aidl} file that declares your parcelable class (as shown for the
+{@code Rect.aidl} file, below).
+ <p>If you are using a custom build process, do <em>not</em> add the {@code .aidl} file to your
+build. Similar to a header file in the C language, this {@code .aidl} file isn't compiled.</p></li>
+</ol>
+
+<p>AIDL will use these methods and fields in the code it generates to marshall and unmarshall
+your objects.</p>
+
+<p>For example, here is a {@code Rect.aidl} file to create a {@code Rect} class that's
+parcelable:</p>
+
+<pre>
+package android.graphics;
+
+// Declare Rect so AIDL can find it and knows that it implements
+// the parcelable protocol.
+parcelable Rect;
+</pre>
+
+<p>And here is an example of how the {@link android.graphics.Rect} class implements the
+{@link android.os.Parcelable} protocol.</p>
+
+<pre>
+import android.os.Parcel;
+import android.os.Parcelable;
+
+public final class Rect implements Parcelable {
+ public int left;
+ public int top;
+ public int right;
+ public int bottom;
+
+ public static final Parcelable.Creator&lt;Rect&gt; CREATOR = new
+Parcelable.Creator&lt;Rect&gt;() {
+ public Rect createFromParcel(Parcel in) {
+ return new Rect(in);
+ }
+
+ public Rect[] newArray(int size) {
+ return new Rect[size];
+ }
+ };
+
+ public Rect() {
+ }
+
+ private Rect(Parcel in) {
+ readFromParcel(in);
+ }
+
+ public void writeToParcel(Parcel out) {
+ out.writeInt(left);
+ out.writeInt(top);
+ out.writeInt(right);
+ out.writeInt(bottom);
+ }
+
+ public void readFromParcel(Parcel in) {
+ left = in.readInt();
+ top = in.readInt();
+ right = in.readInt();
+ bottom = in.readInt();
+ }
+}
+</pre>
+
+<p>The marshalling in the {@code Rect} class is pretty simple. Take a look at the other
+methods on {@link android.os.Parcel} to see the other kinds of values you can write
+to a Parcel.</p>
+
+<p class="warning"><strong>Warning:</strong> Don't forget the security implications of receiving
+data from other processes. In this case, the {@code Rect} will read four numbers from the {@link
+android.os.Parcel}, but it is up to you to ensure that these are within the acceptable range of
+values for whatever the caller is trying to do. See <a
+href="{@docRoot}guide/topics/security/security.html">Security and Permissions</a> for more
+information about how to keep your application secure from malware.</p>
+
diff --git a/docs/html/guide/topics/fundamentals/bound-services.jd b/docs/html/guide/topics/fundamentals/bound-services.jd
new file mode 100644
index 000000000000..e5d626c0799c
--- /dev/null
+++ b/docs/html/guide/topics/fundamentals/bound-services.jd
@@ -0,0 +1,675 @@
+page.title=Bound Services
+parent.title=Services
+parent.link=services.html
+@jd:body
+
+
+<div id="qv-wrapper">
+<ol id="qv">
+<h2>Quickview</h2>
+<ul>
+ <li>A bound service allows other components to bind to it, in order to interact with it and
+perform interprocess communication</li>
+ <li>A bound service is destroyed once all clients unbind, unless the service was also started</li>
+</ul>
+<h2>In this document</h2>
+<ol>
+ <li><a href="#Basics">The Basics</a></li>
+ <li><a href="#Creating">Creating a Bound Service</a>
+ <ol>
+ <li><a href="#Binder">Extending the Binder class</a></li>
+ <li><a href="#Messenger">Using a Messenger</a></li>
+ </ol>
+ </li>
+ <li><a href="#Binding">Binding to a Service</a></li>
+ <li><a href="#Lifecycle">Managing the Lifecycle of a Bound Service</a></li>
+</ol>
+
+<h2>Key classes</h2>
+<ol>
+ <li>{@link android.app.Service}</li>
+ <li>{@link android.content.ServiceConnection}</li>
+ <li>{@link android.os.IBinder}</li>
+</ol>
+
+<h2>Samples</h2>
+<ol>
+ <li><a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/RemoteService.html">{@code
+ RemoteService}</a></li>
+ <li><a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LocalService.html">{@code
+ LocalService}</a></li>
+</ol>
+
+<h2>See also</h2>
+<ol>
+ <li><a href="{@docRoot}guide/topics/fundamentals/services.html">Services</a></li>
+</ol>
+</div>
+
+
+<p>A bound service is the server in a client-server interface. A bound service allows components
+(such as activities) to bind to the service, send requests, receive responses, and even perform
+interprocess communication (IPC). A bound service typically lives only while it serves another
+application component and does not run in the background indefinitely.</p>
+
+<p>This document shows you how to create a bound service, including how to bind
+to the service from other application components. However, you should also refer to the <a
+href="{@docRoot}guide/topics/fundamentals/services.html">Services</a> document for additional
+information about services in general, such as how to deliver notifications from a service, set
+the service to run in the foreground, and more.</p>
+
+
+<h2 id="Basics">The Basics</h2>
+
+<p>A bound service is an implementation of the {@link android.app.Service} class that allows
+other applications to bind to it and interact with it. To provide binding for a
+service, you must implement the {@link android.app.Service#onBind onBind()} callback method. This
+method returns an {@link android.os.IBinder} object that defines the programming interface that
+clients can use to interact with the service.</p>
+
+<div class="sidebox-wrapper">
+<div class="sidebox">
+ <h3>Binding to a Started Service</h3>
+
+<p>As discussed in the <a href="{@docRoot}guide/topics/fundamentals/services.html">Services</a>
+document, you can create a service that is both started and bound. That is, the service can be
+started by calling {@link android.content.Context#startService startService()}, which allows the
+service to run indefinitely, and also allow a client to bind to the service by calling {@link
+android.content.Context#bindService bindService()}.
+ <p>If you do allow your service to be started and bound, then when the service has been
+started, the system does <em>not</em> destroy the service when all clients unbind. Instead, you must
+explicitly stop the service, by calling {@link android.app.Service#stopSelf stopSelf()} or {@link
+android.content.Context#stopService stopService()}.</p>
+
+<p>Although you should usually implement either {@link android.app.Service#onBind onBind()}
+<em>or</em> {@link android.app.Service#onStartCommand onStartCommand()}, it's sometimes necessary to
+implement both. For example, a music player might find it useful to allow its service to run
+indefinitely and also provide binding. This way, an activity can start the service to play some
+music and the music continues to play even if the user leaves the application. Then, when the user
+returns to the application, the activity can bind to the service to regain control of playback.</p>
+
+<p>Be sure to read the section about <a href="#Lifecycle">Managing the Lifecycle of a Bound
+Service</a>, for more information about the service lifecycle when adding binding to a
+started service.</p>
+</div>
+</div>
+
+<p>A client can bind to the service by calling {@link android.content.Context#bindService
+bindService()}. When it does, it must provide an implementation of {@link
+android.content.ServiceConnection}, which monitors the connection with the service. The {@link
+android.content.Context#bindService bindService()} method returns immediately without a value, but
+when the Android system creates the connection between the
+client and service, it calls {@link
+android.content.ServiceConnection#onServiceConnected onServiceConnected()} on the {@link
+android.content.ServiceConnection}, to deliver the {@link android.os.IBinder} that
+the client can use to communicate with the service.</p>
+
+<p>Multiple clients can connect to the service at once. However, the system calls your service's
+{@link android.app.Service#onBind onBind()} method to retrieve the {@link android.os.IBinder} only
+when the first client binds. The system then delivers the same {@link android.os.IBinder} to any
+additional clients that bind, without calling {@link android.app.Service#onBind onBind()} again.</p>
+
+<p>When the last client unbinds from the service, the system destroys the service (unless the
+service was also started by {@link android.content.Context#startService startService()}).</p>
+
+<p>When you implement your bound service, the most important part is defining the interface
+that your {@link android.app.Service#onBind onBind()} callback method returns. There are a few
+different ways you can define your service's {@link android.os.IBinder} interface and the following
+section discusses each technique.</p>
+
+
+
+<h2 id="Creating">Creating a Bound Service</h2>
+
+<p>When creating a service that provides binding, you must provide an {@link android.os.IBinder}
+that provides the programming interface that clients can use to interact with the service. There
+are three ways you can define the interface:</p>
+
+<dl>
+ <dt><a href="#Binder">Extending the Binder class</a></dt>
+ <dd>If your service is private to your own application and runs in the same process as the client
+(which is common), you should create your interface by extending the {@link android.os.Binder} class
+and returning an instance of it from
+{@link android.app.Service#onBind onBind()}. The client receives the {@link android.os.Binder} and
+can use it to directly access public methods available in either the {@link android.os.Binder}
+implementation or even the {@link android.app.Service}.
+ <p>This is the preferred technique when your service is merely a background worker for your own
+application. The only reason you would not create your interface this way is because
+your service is used by other applications or across separate processes.</dd>
+
+ <dt><a href="#Messenger">Using a Messenger</a></dt>
+ <dd>If you need your interface to work across different processes, you can create
+an interface for the service with a {@link android.os.Messenger}. In this manner, the service
+defines a {@link android.os.Handler} that responds to different types of {@link
+android.os.Message} objects. This {@link android.os.Handler}
+is the basis for a {@link android.os.Messenger} that can then share an {@link android.os.IBinder}
+with the client, allowing the client to send commands to the service using {@link
+android.os.Message} objects. Additionally, the client can define a {@link android.os.Messenger} of
+its own so the service can send messages back.
+ <p>This is the simplest way to perform interprocess communication (IPC), because the {@link
+android.os.Messenger} queues all requests into a single thread so that you don't have to design
+your service to be thread-safe.</p>
+ </dd>
+
+ <dt>Using AIDL</dt>
+ <dd>AIDL (Android Interface Definition Language) performs all the work to decompose objects into
+primitives that the operating system can understand and marshall them across processes to perform
+IPC. The previous technique, using a {@link android.os.Messenger}, is actually based on AIDL as
+its underlying structure. As mentioned above, the {@link android.os.Messenger} creates a queue of
+all the client requests in a single thread, so the service receives requests one at a time. If,
+however, you want your service to handle multiple requests simultaneously, then you can use AIDL
+directly. In this case, your service must be capable of multi-threading and be built thread-safe.
+ <p>To use AIDL directly, you must
+create an {@code .aidl} file that defines the programming interface. The Android SDK tools use
+this file to generate an abstract class that implements the interface and handles IPC, which you
+can then extend within your service.</p>
+ </dd>
+</dl>
+
+ <p class="note"><strong>Note:</strong> Most applications <strong>should not</strong> use AIDL to
+create a bound service, because it may require multithreading capabilities and
+can result in a more complicated implementation. As such, AIDL is not suitable for most applications
+and this document does not discuss how to use it for your service. If you're certain that you need
+to use AIDL directly, see the <a href="{@docRoot}guide/topics/advanced/aidl.html">AIDL</a>
+document.</p>
+
+
+
+
+<h3 id="Binder">Extending the Binder class</h3>
+
+<p>If your service is used only by the local application and does not need to work across processes,
+then you can implement your own {@link android.os.Binder} class that provides your client direct
+access to public methods in the service.</p>
+
+<p class="note"><strong>Note:</strong> This works only if the client and service are in the same
+application and process, which is most common. For example, this would work well for a music
+application that needs to bind an activity to its own service that's playing music in the
+background.</p>
+
+<p>Here's how to set it up:</p>
+<ol>
+ <li>In your service, create an instance of {@link android.os.Binder} that either:
+ <ul>
+ <li>contains public methods that the client can call</li>
+ <li>returns the current {@link android.app.Service} instance, which has public methods the
+client can call</li>
+ <li>or, returns an instance of another class hosted by the service with public methods the
+client can call</li>
+ </ul>
+ <li>Return this instance of {@link android.os.Binder} from the {@link
+android.app.Service#onBind onBind()} callback method.</li>
+ <li>In the client, receive the {@link android.os.Binder} from the {@link
+android.content.ServiceConnection#onServiceConnected onServiceConnected()} callback method and
+make calls to the bound service using the methods provided.</li>
+</ol>
+
+<p class="note"><strong>Note:</strong> The reason the service and client must be in the same
+application is so the client can cast the returned object and properly call its APIs. The service
+and client must also be in the same process, because this technique does not perform any
+marshalling across processes.</p>
+
+<p>For example, here's a service that provides clients access to methods in the service through
+a {@link android.os.Binder} implementation:</p>
+
+<pre>
+public class LocalService extends Service {
+ // Binder given to clients
+ private final IBinder mBinder = new LocalBinder();
+ // Random number generator
+ private final Random mGenerator = new Random();
+
+ /**
+ * Class used for the client Binder. Because we know this service always
+ * runs in the same process as its clients, we don't need to deal with IPC.
+ */
+ public class LocalBinder extends Binder {
+ LocalService getService() {
+ // Return this instance of LocalService so clients can call public methods
+ return LocalService.this;
+ }
+ }
+
+ &#64;Override
+ public IBinder onBind(Intent intent) {
+ return mBinder;
+ }
+
+ /** method for clients */
+ public int getRandomNumber() {
+ return mGenerator.nextInt(100);
+ }
+}
+</pre>
+
+<p>The {@code LocalBinder} provides the {@code getService()} method for clients to retrieve the
+current instance of {@code LocalService}. This allows clients to call public methods in the
+service. For example, clients can call {@code getRandomNumber()} from the service.</p>
+
+<p>Here's an activity that binds to {@code LocalService} and calls {@code getRandomNumber()}
+when a button is clicked:</p>
+
+<pre>
+public class BindingActivity extends Activity {
+ LocalService mService;
+ boolean mBound = false;
+
+ &#64;Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.main);
+ }
+
+ &#64;Override
+ protected void onStart() {
+ super.onStart();
+ // Bind to LocalService
+ Intent intent = new Intent(this, LocalService.class);
+ bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
+ }
+
+ &#64;Override
+ protected void onStop() {
+ super.onStop();
+ // Unbind from the service
+ if (mBound) {
+ unbindService(mConnection);
+ mBound = false;
+ }
+ }
+
+ /** Called when a button is clicked (the button in the layout file attaches to
+ * this method with the android:onClick attribute) */
+ public void onButtonClick(View v) {
+ if (mBound) {
+ // Call a method from the LocalService.
+ // However, if this call were something that might hang, then this request should
+ // occur in a separate thread to avoid slowing down the activity performance.
+ int num = mService.getRandomNumber();
+ Toast.makeText(this, "number: " + num, Toast.LENGTH_SHORT).show();
+ }
+ }
+
+ /** Defines callbacks for service binding, passed to bindService() */
+ private ServiceConnection mConnection = new ServiceConnection() {
+
+ &#64;Override
+ public void onServiceConnected(ComponentName className,
+ IBinder service) {
+ // We've bound to LocalService, cast the IBinder and get LocalService instance
+ LocalBinder binder = (LocalBinder) service;
+ mService = binder.getService();
+ mBound = true;
+ }
+
+ &#64;Override
+ public void onServiceDisconnected(ComponentName arg0) {
+ mBound = false;
+ }
+ };
+}
+</pre>
+
+<p>The above sample shows how the client binds to the service using an implementation of
+{@link android.content.ServiceConnection} and the {@link
+android.content.ServiceConnection#onServiceConnected onServiceConnected()} callback. The next
+section provides more information about this process of binding to the service.</p>
+
+<p class="note"><strong>Note:</strong> The example above doesn't explicitly unbind from the service,
+but all clients should unbind at an appropriate time (such as when the activity pauses).</p>
+
+<p>For more sample code, see the <a
+href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LocalService.html">{@code
+LocalService.java}</a> class and the <a
+href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LocalServiceActivities.html">{@code
+LocalServiceActivities.java}</a> class in <a
+href="{@docRoot}resources/samples/ApiDemos/index.html">ApiDemos</a>.</p>
+
+
+
+
+
+<h3 id="Messenger">Using a Messenger</h3>
+
+<div class="sidebox-wrapper">
+<div class="sidebox">
+ <h4>Compared to AIDL</h4>
+ <p>When you need to perform IPC, using a {@link android.os.Messenger} for your interface is
+simpler than implementing it with AIDL, because {@link android.os.Messenger} queues
+all calls to the service, whereas, a pure AIDL interface sends simultaneous requests to the
+service, which must then handle multi-threading.</p>
+ <p>For most applications, the service doesn't need to perform multi-threading, so using a {@link
+android.os.Messenger} allows the service to handle one call at a time. If it's important
+that your service be multi-threaded, then you should use <a
+href="{@docRoot}guide/topics/advanced/aidl.html">AIDL</a> to define your interface.</p>
+</div>
+</div>
+
+<p>If you need your service to communicate with remote processes, then you can use a
+{@link android.os.Messenger} to provide the interface for your service. This technique allows
+you to perform interprocess communication (IPC) without the need to use AIDL.</p>
+
+<p>Here's a summary of how to use a {@link android.os.Messenger}:</p>
+
+<ul>
+ <li>The service implements a {@link android.os.Handler} that receives a callback for each
+call from a client.</li>
+ <li>The {@link android.os.Handler} is used to create a {@link android.os.Messenger} object
+(which is a reference to the {@link android.os.Handler}).</li>
+ <li>The {@link android.os.Messenger} creates an {@link android.os.IBinder} that the service
+returns to clients from {@link android.app.Service#onBind onBind()}.</li>
+ <li>Clients use the {@link android.os.IBinder} to instantiate the {@link android.os.Messenger}
+(that references the service's {@link android.os.Handler}), which the client uses to send
+{@link android.os.Message} objects to the service.</li>
+ <li>The service receives each {@link android.os.Message} in its {@link
+android.os.Handler}&mdash;specifically, in the {@link android.os.Handler#handleMessage
+handleMessage()} method.</li>
+</ul>
+
+
+<p>In this way, there are no "methods" for the client to call on the service. Instead, the
+client delivers "messages" ({@link android.os.Message} objects) that the service receives in
+its {@link android.os.Handler}.</p>
+
+<p>Here's a simple example service that uses a {@link android.os.Messenger} interface:</p>
+
+<pre>
+public class MessengerService extends Service {
+ /** Command to the service to display a message */
+ static final int MSG_SAY_HELLO = 1;
+
+ /**
+ * Handler of incoming messages from clients.
+ */
+ class IncomingHandler extends Handler {
+ &#64;Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MSG_SAY_HELLO:
+ Toast.makeText(getApplicationContext(), "hello!", Toast.LENGTH_SHORT).show();
+ break;
+ default:
+ super.handleMessage(msg);
+ }
+ }
+ }
+
+ /**
+ * Target we publish for clients to send messages to IncomingHandler.
+ */
+ final Messenger mMessenger = new Messenger(new IncomingHandler());
+
+ /**
+ * When binding to the service, we return an interface to our messenger
+ * for sending messages to the service.
+ */
+ &#64;Override
+ public IBinder onBind(Intent intent) {
+ Toast.makeText(getApplicationContext(), "binding", Toast.LENGTH_SHORT).show();
+ return mMessenger.getBinder();
+ }
+}
+</pre>
+
+<p>Notice that the {@link android.os.Handler#handleMessage handleMessage()} method in the
+{@link android.os.Handler} is where the service receives the incoming {@link android.os.Message}
+and decides what to do, based on the {@link android.os.Message#what} member.</p>
+
+<p>All that a client needs to do is create a {@link android.os.Messenger} based on the {@link
+android.os.IBinder} returned by the service and send a message using {@link
+android.os.Messenger#send send()}. For example, here's a simple activity that binds to the
+service and delivers the {@code MSG_SAY_HELLO} message to the service:</p>
+
+<pre>
+public class ActivityMessenger extends Activity {
+ /** Messenger for communicating with the service. */
+ Messenger mService = null;
+
+ /** Flag indicating whether we have called bind on the service. */
+ boolean mBound;
+
+ /**
+ * Class for interacting with the main interface of the service.
+ */
+ private ServiceConnection mConnection = new ServiceConnection() {
+ public void onServiceConnected(ComponentName className, IBinder service) {
+ // This is called when the connection with the service has been
+ // established, giving us the object we can use to
+ // interact with the service. We are communicating with the
+ // service using a Messenger, so here we get a client-side
+ // representation of that from the raw IBinder object.
+ mService = new Messenger(service);
+ mBound = true;
+ }
+
+ public void onServiceDisconnected(ComponentName className) {
+ // This is called when the connection with the service has been
+ // unexpectedly disconnected -- that is, its process crashed.
+ mService = null;
+ mBound = false;
+ }
+ };
+
+ public void sayHello(View v) {
+ if (!mBound) return;
+ // Create and send a message to the service, using a supported 'what' value
+ Message msg = Message.obtain(null, MessengerService.MSG_SAY_HELLO, 0, 0);
+ try {
+ mService.send(msg);
+ } catch (RemoteException e) {
+ e.printStackTrace();
+ }
+ }
+
+ &#64;Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.main);
+ }
+
+ &#64;Override
+ protected void onStart() {
+ super.onStart();
+ // Bind to the service
+ bindService(new Intent(this, MessengerService.class), mConnection,
+ Context.BIND_AUTO_CREATE);
+ }
+
+ &#64;Override
+ protected void onStop() {
+ super.onStop();
+ // Unbind from the service
+ if (mBound) {
+ unbindService(mConnection);
+ mBound = false;
+ }
+ }
+}
+</pre>
+
+<p>Notice that this example does not show how the service can respond to the client. If you want the
+service to respond, then you need to also create a {@link android.os.Messenger} in the client. Then
+when the client receives the {@link android.content.ServiceConnection#onServiceConnected
+onServiceConnected()} callback, it sends a {@link android.os.Message} to the service that includes
+the client's {@link android.os.Messenger} in the {@link android.os.Message#replyTo} parameter
+of the {@link android.os.Messenger#send send()} method.</p>
+
+<p>You can see an example of how to provide two-way messaging in the <a
+href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/MessengerService.html">{@code
+MessengerService.java}</a> (service) and <a
+href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/MessengerServiceActivities.html">{@code
+MessengerServiceActivities.java}</a> (client) samples.</p>
+
+
+
+
+
+<h2 id="Binding">Binding to a Service</h2>
+
+<p>Application components (clients) can bind to a service by calling
+{@link android.content.Context#bindService bindService()}. The Android
+system then calls the service's {@link android.app.Service#onBind
+onBind()} method, which returns an {@link android.os.IBinder} for interacting with the service.</p>
+
+<p>The binding is asynchronous. {@link android.content.Context#bindService
+bindService()} returns immediately and does <em>not</em> return the {@link android.os.IBinder} to
+the client. To receive the {@link android.os.IBinder}, the client must create an instance of {@link
+android.content.ServiceConnection} and pass it to {@link android.content.Context#bindService
+bindService()}. The {@link android.content.ServiceConnection} includes a callback method that the
+system calls to deliver the {@link android.os.IBinder}.</p>
+
+<p class="note"><strong>Note:</strong> Only activities, services, and content providers can bind
+to a service&mdash;you <strong>cannot</strong> bind to a service from a broadcast receiver.</p>
+
+<p>So, to bind to a service from your client, you must: </p>
+<ol>
+ <li>Implement {@link android.content.ServiceConnection}.
+ <p>Your implementation must override two callback methods:</p>
+ <dl>
+ <dt>{@link android.content.ServiceConnection#onServiceConnected onServiceConnected()}</dt>
+ <dd>The system calls this to deliver the {@link android.os.IBinder} returned by
+the service's {@link android.app.Service#onBind onBind()} method.</dd>
+ <dt>{@link android.content.ServiceConnection#onServiceDisconnected
+onServiceDisconnected()}</dt>
+ <dd>The Android system calls this when the connection to the service is unexpectedly
+lost, such as when the service has crashed or has been killed. This is <em>not</em> called when the
+client unbinds.</dd>
+ </dl>
+ </li>
+ <li>Call {@link
+android.content.Context#bindService bindService()}, passing the {@link
+android.content.ServiceConnection} implementation. </li>
+ <li>When the system calls your {@link android.content.ServiceConnection#onServiceConnected
+onServiceConnected()} callback method, you can begin making calls to the service, using
+the methods defined by the interface.</li>
+ <li>To disconnect from the service, call {@link
+android.content.Context#unbindService unbindService()}.
+ <p>When your client is destroyed, it will unbind from the service, but you should always unbind
+when you're done interacting with the service or when your activity pauses so that the service can
+shutdown while its not being used. (Appropriate times to bind and unbind is discussed
+more below.)</p>
+ </li>
+</ol>
+
+<p>For example, the following snippet connects the client to the service created above by
+<a href="#Binder">extending the Binder class</a>, so all it must do is cast the returned
+{@link android.os.IBinder} to the {@code LocalService} class and request the {@code
+LocalService} instance:</p>
+
+<pre>
+LocalService mService;
+private ServiceConnection mConnection = new ServiceConnection() {
+ // Called when the connection with the service is established
+ public void onServiceConnected(ComponentName className, IBinder service) {
+ // Because we have bound to an explicit
+ // service that is running in our own process, we can
+ // cast its IBinder to a concrete class and directly access it.
+ LocalBinder binder = (LocalBinder) service;
+ mService = binder.getService();
+ mBound = true;
+ }
+
+ // Called when the connection with the service disconnects unexpectedly
+ public void onServiceDisconnected(ComponentName className) {
+ Log.e(TAG, "onServiceDisconnected");
+ mBound = false;
+ }
+};
+</pre>
+
+<p>With this {@link android.content.ServiceConnection}, the client can bind to a service by passing
+this it to {@link android.content.Context#bindService bindService()}. For example:</p>
+
+<pre>
+Intent intent = new Intent(this, LocalService.class);
+bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
+</pre>
+
+<ul>
+ <li>The first parameter of {@link android.content.Context#bindService bindService()} is an
+{@link android.content.Intent} that explicitly names the service to bind (thought the intent
+could be implicit).</li>
+<li>The second parameter is the {@link android.content.ServiceConnection} object.</li>
+<li>The third parameter is a flag indicating options for the binding. It should usually be {@link
+android.content.Context#BIND_AUTO_CREATE} in order to create the service if its not already alive.
+Other possible values are {@link android.content.Context#BIND_DEBUG_UNBIND}
+and {@link android.content.Context#BIND_NOT_FOREGROUND}, or {@code 0} for none.</li>
+</ul>
+
+
+<h3>Additional notes</h3>
+
+<p>Here are some important notes about binding to a service:</p>
+<ul>
+ <li>You should always trap {@link android.os.DeadObjectException} exceptions, which are thrown
+when the connection has broken. This is the only exception thrown by remote methods.</li>
+ <li>Objects are reference counted across processes. </li>
+ <li>You should usually pair the binding and unbinding during
+matching bring-up and tear-down moments of the client's lifecycle. For example:
+ <ul>
+ <li>If you only need to interact with the service while your activity is visible, you
+should bind during {@link android.app.Activity#onStart onStart()} and unbind during {@link
+android.app.Activity#onStop onStop()}.</li>
+ <li>If you want your activity to receive responses even while it is stopped in the
+background, then you can bind during {@link android.app.Activity#onCreate onCreate()} and unbind
+during {@link android.app.Activity#onDestroy onDestroy()}. Beware that this implies that your
+activity needs to use the service the entire time it's running (even in the background), so if
+the service is in another process, then you increase the weight of the process and it becomes
+more likely that the system will kill it.</li>
+ </ul>
+ <p class="note"><strong>Note:</strong> You should usually <strong>not</strong> bind and unbind
+during your activity's {@link android.app.Activity#onResume onResume()} and {@link
+android.app.Activity#onPause onPause()}, because these callbacks occur at every lifecycle transition
+and you should keep the processing that occurs at these transitions to a minimum. Also, if
+multiple activities in your application bind to the same service and there is a transition between
+two of those activities, the service may be destroyed and recreated as the current activity unbinds
+(during pause) before the next one binds (during resume). (This activity transition for how
+activities coordinate their lifecycles is described in the <a
+href="{@docRoot}guide/topics/fundamentals/activities.html#CoordinatingActivities">Activities</a>
+document.)</p>
+</ul>
+
+<p>For more sample code, showing how to bind to a service, see the <a
+href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/RemoteService.html">{@code
+RemoteService.java}</a> class in <a
+href="{@docRoot}resources/samples/ApiDemos/index.html">ApiDemos</a>.</p>
+
+
+
+
+
+<h2 id="Lifecycle">Managing the Lifecycle of a Bound Service</h2>
+
+<div class="figure" style="width:588px">
+<img src="{@docRoot}images/fundamentals/service_binding_tree_lifecycle.png" alt="" />
+<p class="img-caption"><strong>Figure 1.</strong> The lifecycle for a service that is started
+and also allows binding.</p>
+</div>
+
+<p>When a service is unbound from all clients, the Android system destroys it (unless it was also
+started with {@link android.app.Service#onStartCommand onStartCommand()}). As such, you don't have
+to manage the lifecycle of your service if it's purely a bound
+service&mdash;the Android system manages it for you based on whether it is bound to any clients.</p>
+
+<p>However, if you choose to implement the {@link android.app.Service#onStartCommand
+onStartCommand()} callback method, then you must explicitly stop the service, because the
+service is now considered to be <em>started</em>. In this case, the service runs until the service
+stops itself with {@link android.app.Service#stopSelf()} or another component calls {@link
+android.content.Context#stopService stopService()}, regardless of whether it is bound to any
+clients.</p>
+
+<p>Additionally, if your service is started and accepts binding, then when the system calls
+your {@link android.app.Service#onUnbind onUnbind()} method, you can optionally return
+{@code true} if you would like to receive a call to {@link android.app.Service#onRebind
+onRebind()} the next time a client binds to the service (instead of receiving a call to {@link
+android.app.Service#onBind onBind()}). {@link android.app.Service#onRebind
+onRebind()} returns void, but the client still receives the {@link android.os.IBinder} in its
+{@link android.content.ServiceConnection#onServiceConnected onServiceConnected()} callback.
+Below, figure 1 illustrates the logic for this kind of lifecycle.</p>
+
+<p>For more information about the lifecycle of an started service, see the <a
+href="{@docRoot}guide/topics/fundamentals/services.html#Lifecycle">Services</a> document.</p>
+
+
+
+
diff --git a/docs/html/guide/topics/fundamentals/services.jd b/docs/html/guide/topics/fundamentals/services.jd
new file mode 100644
index 000000000000..df1eacee5029
--- /dev/null
+++ b/docs/html/guide/topics/fundamentals/services.jd
@@ -0,0 +1,860 @@
+page.title=Services
+parent.title=Application Fundamentals
+parent.link=index.html
+@jd:body
+
+<div id="qv-wrapper">
+<ol id="qv">
+<h2>Quickview</h2>
+<ul>
+ <li>A service can run in the background to perform work even while the user is in a different
+application</li>
+ <li>A service can allow other components to bind to it, in order to interact with it and
+perform interprocess communication</li>
+ <li>A service runs in the main thread of the application that hosts it, by default</li>
+</ul>
+<h2>In this document</h2>
+<ol>
+<li><a href="#Basics">The Basics</a></li>
+<ol>
+ <li><a href="#Declaring">Declaring a service in the manifest</a></li>
+</ol>
+<li><a href="#CreatingAService">Creating a Started Service</a>
+ <ol>
+ <li><a href="#ExtendingIntentService">Extending the IntentService class</a></li>
+ <li><a href="#ExtendingService">Extending the Service class</a></li>
+ <li><a href="#StartingAService">Starting a service</a></li>
+ <li><a href="#Stopping">Stopping a service</a></li>
+ </ol>
+</li>
+<li><a href="#CreatingBoundService">Creating a Bound Service</a></li>
+<li><a href="#Notifications">Sending Notifications to the User</a></li>
+<li><a href="#Foreground">Running a Service in the Foreground</a></li>
+<li><a href="#Lifecycle">Managing the Lifecycle of a Service</a>
+<ol>
+ <li><a href="#LifecycleCallbacks">Implementing the lifecycle callbacks</a></li>
+</ol>
+</li>
+</ol>
+
+<h2>Key classes</h2>
+<ol>
+ <li>{@link android.app.Service}</li>
+ <li>{@link android.app.IntentService}</li>
+</ol>
+
+<h2>Samples</h2>
+<ol>
+ <li><a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/ServiceStartArguments.html">{@code
+ ServiceStartArguments}</a></li>
+ <li><a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LocalService.html">{@code
+ LocalService}</a></li>
+</ol>
+
+<h2>See also</h2>
+<ol>
+<li><a href="{@docRoot}guide/topics/fundamentals/bound-services.html">Bound Services</a></li>
+</ol>
+
+</div>
+
+
+<p>A {@link android.app.Service} is an application component that can perform
+long-running operations in the background and does not provide a user interface. Another
+application component can start a service and it will continue to run in the background even if the
+user switches to another application. Additionally, a component can bind to a service to
+interact with it and even perform interprocess communication (IPC). For example, a service might
+handle network transactions, play music, perform file I/O, or interact with a content provider, all
+from the background.</p>
+
+<p>A service can essentially take two forms:</p>
+
+<dl>
+ <dt>Started</dt>
+ <dd>A service is "started" when an application component (such as an activity) starts it by
+calling {@link android.content.Context#startService startService()}. Once started, a service
+can run in the background indefinitely, even if the component that started it is destroyed. Usually,
+a started service performs a single operation and does not return a result to the caller.
+For example, it might download or upload a file over the network. When the operation is done, the
+service should stop itself.</dd>
+ <dt>Bound</dt>
+ <dd>A service is "bound" when an application component binds to it by calling {@link
+android.content.Context#bindService bindService()}. A bound service offers a client-server
+interface that allows components to interact with the service, send requests, get results, and even
+do so across processes with interprocess communication (IPC). A bound service runs only as long as
+another application component is bound to it. Multiple components can bind to the service at once,
+but when all of them unbind, the service is destroyed.</dd>
+</dl>
+
+<p>Although this documentation generally discusses these two types of services separately, your
+service can work both ways&mdash;it can be started (to run indefinitely) and also allow binding.
+It's simply a matter of whether you implement a couple callback methods: {@link
+android.app.Service#onStartCommand onStartCommand()} to allow components to start it and {@link
+android.app.Service#onBind onBind()} to allow binding.</p>
+
+<p>Regardless of whether your application is started, bound, or both, any application component
+can use the service (even from a separate application), in the same way that any component can use
+an activity&mdash;by starting it with an {@link android.content.Intent}. However, you can declare
+the service as private, in the manifest file, and block access from other applications. This is
+discussed more in the section about <a href="#Declaring">Declaring the service in the
+manifest</a>.</p>
+
+<p class="caution"><strong>Caution:</strong> A service runs in the
+main thread of its hosting process&mdash;the service does <strong>not</strong> create its own thread
+and does <strong>not</strong> run in a separate process (unless you specify otherwise). This means
+that, if your service is going to do any CPU intensive work or blocking operations (such as MP3
+playback or networking), you should create a new thread within the service to do that work. By using
+a separate thread, you will reduce the risk of Application Not Responding (ANR) errors and the
+application's main thread can remain dedicated to user interaction with your activities.</p>
+
+
+<h2 id="Basics">The Basics</h2>
+
+<div class="sidebox-wrapper">
+<div class="sidebox">
+ <h3>Should you use a service or a thread?</h3>
+ <p>A service is simply a component that can run in the background even when the user is not
+interacting with your application. Thus, you should create a service only if that is what you
+need.</p>
+ <p>If you need to perform work outside your main thread, but only while the user is interacting
+with your application, then you should probably instead create a new thread and not a service. For
+example, if you want to play some music, but only while your activity is running, you might create
+a thread in {@link android.app.Activity#onCreate onCreate()}, start running it in {@link
+android.app.Activity#onStart onStart()}, then stop it in {@link android.app.Activity#onStop
+onStop()}. Also consider using {@link android.os.AsyncTask} or {@link android.os.HandlerThread},
+instead of the traditional {@link java.lang.Thread} class. See the <a
+href="{@docRoot}guide/topics/fundamentals/processes-and-threading.html#Threads">Processes and
+Threading</a> document for more information about threads.</p>
+ <p>Remember that if you do use a service, it still runs in your application's main thread by
+default, so you should still create a new thread within the service if it performs intensive or
+blocking operations.</p>
+</div>
+</div>
+
+<p>To create a service, you must create a subclass of {@link android.app.Service} (or one
+of its existing subclasses). In your implementation, you need to override some callback methods that
+handle key aspects of the service lifecycle and provide a mechanism for components to bind to
+the service, if appropriate. The most important callback methods you should override are:</p>
+
+<dl>
+ <dt>{@link android.app.Service#onStartCommand onStartCommand()}</dt>
+ <dd>The system calls this method when another component, such as an activity,
+requests that the service be started, by calling {@link android.content.Context#startService
+startService()}. Once this method executes, the service is started and can run in the
+background indefinitely. If you implement this, it is your responsibility to stop the service when
+its work is done, by calling {@link android.app.Service#stopSelf stopSelf()} or {@link
+android.content.Context#stopService stopService()}. (If you only want to provide binding, you don't
+need to implement this method.)</dd>
+ <dt>{@link android.app.Service#onBind onBind()}</dt>
+ <dd>The system calls this method when another component wants to bind with the
+service (such as to perform RPC), by calling {@link android.content.Context#bindService
+bindService()}. In your implementation of this method, you must provide an interface that clients
+use to communicate with the service, by returning an {@link android.os.IBinder}. You must always
+implement this method, but if you don't want to allow binding, then you should return null.</dd>
+ <dt>{@link android.app.Service#onCreate()}</dt>
+ <dd>The system calls this method when the service is first created, to perform one-time setup
+procedures (before it calls either {@link android.app.Service#onStartCommand onStartCommand()} or
+{@link android.app.Service#onBind onBind()}). If the service is already running, this method is not
+called.</dd>
+ <dt>{@link android.app.Service#onDestroy()}</dt>
+ <dd>The system calls this method when the service is no longer used and is being destroyed.
+Your service should implement this to clean up any resources such as threads, registered
+listeners, receivers, etc. This is the last call the service receives.</dd>
+</dl>
+
+<p>If a component starts the service by calling {@link
+android.content.Context#startService startService()} (which results in a call to {@link
+android.app.Service#onStartCommand onStartCommand()}), then the service
+remains running until it stops itself with {@link android.app.Service#stopSelf()} or another
+component stops it by calling {@link android.content.Context#stopService stopService()}.</p>
+
+<p>If a component calls
+{@link android.content.Context#bindService bindService()} to create the service (and {@link
+android.app.Service#onStartCommand onStartCommand()} is <em>not</em> called), then the service runs
+only as long as the component is bound to it. Once the service is unbound from all clients, the
+system destroys it.</p>
+
+<p>The Android system will force-stop a service only when memory is low and it must recover system
+resources for the activity that has user focus. If the service is bound to an activity that has user
+focus, then it's less likely to be killed, and if the service is declared to <a
+href="#Foreground">run in the foreground</a> (discussed later), then it will almost never be killed.
+Otherwise, if the service was started and is long-running, then the system will lower its position
+in the list of background tasks over time and the service will become highly susceptible to
+killing&mdash;if your service is started, then you must design it to gracefully handle restarts
+by the system. If the system kills your service, it restarts it as soon as resources become
+available again (though this also depends on the value you return from {@link
+android.app.Service#onStartCommand onStartCommand()}, as discussed later). For more information
+about when the system might destroy a service, see the <a
+href="{@docRoot}guide/topics/fundamentals/processes-and-threading.html">Processes and Threading</a>
+document.</p>
+
+<p>In the following sections, you'll see how you can create each type of service and how to use
+it from other application components.</p>
+
+
+
+<h3 id="Declaring">Declaring a service in the manifest</h3>
+
+<p>Like activities (and other components), you must declare all services in your application's
+manifest file.</p>
+
+<p>To decalare your service, add a <a
+href="{@docRoot}guide/topics/manifest/service-element.html">{@code &lt;service&gt;}</a> element
+as a child of the <a
+href="{@docRoot}guide/topics/manifest/application-element.html">{@code &lt;application&gt;}</a>
+element. For example:</p>
+
+<pre>
+&lt;manifest ... &gt;
+ ...
+ &lt;application ... &gt;
+ &lt;service android:name=".ExampleService" /&gt;
+ ...
+ &lt;/application&gt;
+&lt;/manifest&gt;
+</pre>
+
+<p>There are other attributes you can include in the <a
+href="{@docRoot}guide/topics/manifest/service-element.html">{@code &lt;service&gt;}</a> element to
+define properties such as permissions required to start the service and the process in
+which the service should run. See the <a
+href="{@docRoot}guide/topics/manifest/service-element.html">{@code &lt;service&gt;}</a> element
+reference for more information.</p>
+
+<p>Just like an activity, a service can define intent filters that allow other components to
+invoke the service using implicit intents. By declaring intent filters, components
+from any application installed on the user's device can potentially start your service if your
+service declares an intent filter that matches the intent another application passes to {@link
+android.content.Context#startService startService()}.</p>
+
+<p>If you plan on using your service only locally (other applications do not use it), then you
+don't need to (and should not) supply any intent filters. Without any intent filters, you must
+start the service using an intent that explicitly names the service class. More information
+about <a href="#StartingAService">starting a service</a> is discussed below.</p>
+
+<p>Additionally, you can ensure that your service is private to your application only if
+you include the <a
+href="{@docRoot}guide/topics/manifest/service-element.html#exported">{@code android:exported}</a>
+attribute and set it to {@code "false"}. This is effective even if your service supplies intent
+filters.</p>
+
+<p>For more information about creating intent filters for your service, see the <a
+href="{@docRoot}guide/topics/intents/intents-filters.html">Intents and Intent Filters</a>
+document.</p>
+
+
+
+<h2 id="CreatingStartedService">Creating a Started Service</h2>
+
+<div class="sidebox-wrapper">
+<div class="sidebox">
+ <h2>Targeting Android 1.6 or lower</h2>
+ <p>If you're building an application for Android 1.6 or lower, you need
+to implement {@link android.app.Service#onStart onStart()}, instead of {@link
+android.app.Service#onStartCommand onStartCommand()} (in Android 2.0,
+{@link android.app.Service#onStart onStart()} was deprecated in favor of {@link
+android.app.Service#onStartCommand onStartCommand()}).</p>
+ <p>For more information about providing compatibility with versions of Android older than 2.0, see
+the {@link android.app.Service#onStartCommand onStartCommand()} documentation.</p>
+</div>
+</div>
+
+<p>A started service is one that another component starts by calling {@link
+android.content.Context#startService startService()}, resulting in a call to the service's
+{@link android.app.Service#onStartCommand onStartCommand()} method.</p>
+
+<p>When a service is started, it has a lifecycle that's independent of the
+component that started it and the service can run in the background indefinitely, even if
+the component that started it is destroyed. As such, the service should stop itself when its job
+is done by calling {@link android.app.Service#stopSelf stopSelf()}, or another component can stop it
+by calling {@link android.content.Context#stopService stopService()}.</p>
+
+<p>An application component such as an activity can start the service by calling {@link
+android.content.Context#startService startService()} and passing an {@link android.content.Intent}
+that specifies the service and includes any data for the service to use. The service receives
+this {@link android.content.Intent} in the {@link android.app.Service#onStartCommand
+onStartCommand()} method.</p>
+
+<p>For instance, suppose an activity needs to save some data to an online database. The activity can
+start a companion service and deliver it the data to save by passing an intent to {@link
+android.content.Context#startService startService()}. The service receives the intent in {@link
+android.app.Service#onStartCommand onStartCommand()}, connects to the Internet and performs the
+database transaction. When the transaction is done, the service stops itself and it is
+destroyed.</p>
+
+<p class="caution"><strong>Caution:</strong> A services runs in the same process as the application
+in which it is declared and in the main thread of that application, by default. So, if your service
+performs intensive or blocking operations while the user interacts with an activity from the same
+application, the service will slow down activity performance. To avoid impacting application
+performance, you should start a new thread inside the service.</p>
+
+<p>Traditionally, there are two classes you can extend to create a started service:</p>
+<dl>
+ <dt>{@link android.app.Service}</dt>
+ <dd>This is the base class for all services. When you extend this class, it's important that
+you create a new thread in which to do all the service's work, because the service uses your
+application's main thread, by default, which could slow the performance of any activity your
+application is running.</dd>
+ <dt>{@link android.app.IntentService}</dt>
+ <dd>This is a subclass of {@link android.app.Service} that uses a worker thread to handle all
+start requests, one at a time. This is the best option if you don't require that your service
+handle multiple requests simultaneously. All you need to do is implement {@link
+android.app.IntentService#onHandleIntent onHandleIntent()}, which receives the intent for each
+start request so you can do the background work.</dd>
+</dl>
+
+<p>The following sections describe how you can implement your service using either one for these
+classes.</p>
+
+
+<h3 id="ExtendingIntentService">Extending the IntentService class</h3>
+
+<p>Because most started services don't need to handle multiple requests simultaneously
+(which can actually be a dangerous multi-threading scenario), it's probably best if you
+implement your service using the {@link android.app.IntentService} class.</p>
+
+<p>The {@link android.app.IntentService} does the following:</p>
+
+<ul>
+ <li>Creates a default worker thread that executes all intents delivered to {@link
+android.app.Service#onStartCommand onStartCommand()} separate from your application's main
+thread.</li>
+ <li>Creates a work queue that passes one intent at a time to your {@link
+android.app.IntentService#onHandleIntent onHandleIntent()} implementation, so you never have to
+worry about multi-threading.</li>
+ <li>Stops the service after all start requests have been handled, so you never have to call
+{@link android.app.Service#stopSelf}.</li>
+ <li>Provides default implementation of {@link android.app.IntentService#onBind onBind()} that
+returns null.</li>
+ <li>Provides a default implementation of {@link android.app.IntentService#onStartCommand
+onStartCommand()} that sends the intent to the work queue and then to your {@link
+android.app.IntentService#onHandleIntent onHandleIntent()} implementation.</li>
+</ul>
+
+<p>All this adds up to the fact that all you need to do is implement {@link
+android.app.IntentService#onHandleIntent onHandleIntent()} to do the work provided by the
+client. (Though, you also need to provide a small constructor for the service.)</p>
+
+<p>Here's an example implementation of {@link android.app.IntentService}:</p>
+
+<pre>
+public class HelloIntentService extends IntentService {
+
+ /**
+ * A constructor is required, and must call the super {@link android.app.IntentService#IntentService}
+ * constructor with a name for the worker thread.
+ */
+ public HelloIntentService() {
+ super("HelloIntentService");
+ }
+
+ /**
+ * The IntentService calls this method from the default worker thread with
+ * the intent that started the service. When this method returns, IntentService
+ * stops the service, as appropriate.
+ */
+ &#64;Override
+ protected void onHandleIntent(Intent intent) {
+ // Normally we would do some work here, like download a file.
+ // For our sample, we just sleep for 5 seconds.
+ long endTime = System.currentTimeMillis() + 5*1000;
+ while (System.currentTimeMillis() &lt; endTime) {
+ synchronized (this) {
+ try {
+ wait(endTime - System.currentTimeMillis());
+ } catch (Exception e) {
+ }
+ }
+ }
+ }
+}
+</pre>
+
+<p>That's all you need: a constructor and an implementation of {@link
+android.app.IntentService#onHandleIntent onHandleIntent()}.</p>
+
+<p>If you decide to also override other callback methods, such as {@link
+android.app.IntentService#onCreate onCreate()}, {@link
+android.app.IntentService#onStartCommand onStartCommand()}, or {@link
+android.app.IntentService#onDestroy onDestroy()}, be sure to call the super implementation, so
+that the {@link android.app.IntentService} can properly handle the life of the worker thread.</p>
+
+<p>For example, {@link android.app.IntentService#onStartCommand onStartCommand()} must return
+the default implementation (which is how the intent gets delivered to {@link
+android.app.IntentService#onHandleIntent onHandleIntent()}):</p>
+
+<pre>
+&#64;Override
+public int onStartCommand(Intent intent, int flags, int startId) {
+ Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();
+ return super.onStartCommand(intent,flags,startId);
+}
+</pre>
+
+<p>Besides {@link android.app.IntentService#onHandleIntent onHandleIntent()}, the only method
+from which you don't need to call the super class is {@link android.app.IntentService#onBind
+onBind()} (but you only need to implement that if your service allows binding).</p>
+
+<p>In the next section, you'll see how the same kind of service is implemented when extending
+the base {@link android.app.Service} class, which is a lot more code, but which might be
+appropriate if you need to handle simultaneous start requests.</p>
+
+
+<h3 id="ExtendingService">Extending the Service class</h3>
+
+<p>As you saw in the previous section, using {@link android.app.IntentService} makes your
+implementation of a started service very simple. If, however, you require your service to
+perform multi-threading (instead of processing start requests through a work queue), then you
+can extend the {@link android.app.Service} class to handle each intent.</p>
+
+<p>For comparison, the following example code is an implementation of the {@link
+android.app.Service} class that performs the exact same work as the example above using {@link
+android.app.IntentService}. That is, for each start request, it uses a worker thread to perform the
+job and processes only one request at a time.</p>
+
+<pre>
+public class HelloService extends Service {
+ private Looper mServiceLooper;
+ private ServiceHandler mServiceHandler;
+
+ // Handler that receives messages from the thread
+ private final class ServiceHandler extends Handler {
+ public ServiceHandler(Looper looper) {
+ super(looper);
+ }
+ &#64;Override
+ public void handleMessage(Message msg) {
+ // Normally we would do some work here, like download a file.
+ // For our sample, we just sleep for 5 seconds.
+ long endTime = System.currentTimeMillis() + 5*1000;
+ while (System.currentTimeMillis() &lt; endTime) {
+ synchronized (this) {
+ try {
+ wait(endTime - System.currentTimeMillis());
+ } catch (Exception e) {
+ }
+ }
+ }
+ // Stop the service using the startId, so that we don't stop
+ // the service in the middle of handling another job
+ stopSelf(msg.arg1);
+ }
+ }
+
+ &#64;Override
+ public void onCreate() {
+ // Start up the thread running the service. Note that we create a
+ // separate thread because the service normally runs in the process's
+ // main thread, which we don't want to block. We also make it
+ // background priority so CPU-intensive work will not disrupt our UI.
+ HandlerThread thread = new HandlerThread("ServiceStartArguments",
+ Process.THREAD_PRIORITY_BACKGROUND);
+ thread.start();
+
+ // Get the HandlerThread's Looper and use it for our Handler
+ mServiceLooper = thread.getLooper();
+ mServiceHandler = new ServiceHandler(mServiceLooper);
+ }
+
+ &#64;Override
+ public int onStartCommand(Intent intent, int flags, int startId) {
+ Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();
+
+ // For each start request, send a message to start a job and deliver the
+ // start ID so we know which request we're stopping when we finish the job
+ Message msg = mServiceHandler.obtainMessage();
+ msg.arg1 = startId;
+ mServiceHandler.sendMessage(msg);
+
+ // If we get killed, after returning from here, restart
+ return START_STICKY;
+ }
+
+ &#64;Override
+ public IBinder onBind(Intent intent) {
+ // We don't provide binding, so return null
+ return null;
+ }
+
+ &#64;Override
+ public void onDestroy() {
+ Toast.makeText(this, "service done", Toast.LENGTH_SHORT).show();
+ }
+}
+</pre>
+
+<p>As you can see, it's a lot more work than using {@link android.app.IntentService}.</p>
+
+<p>However, because you handle each call to {@link android.app.Service#onStartCommand
+onStartCommand()} yourself, you can perform multiple requests simultaneously. That's not what
+this example does, but if that's what you want, then you can create a new thread for each
+request and run them right away (instead of waiting for the previous request to finish).</p>
+
+<p>Notice that the {@link android.app.Service#onStartCommand onStartCommand()} method must return an
+integer. The integer is a value that describes how the system should continue the service in the
+event that the system kills it (as discussed above, the default implementation for {@link
+android.app.IntentService} handles this for you, though you are able to modify it). The return value
+from {@link android.app.Service#onStartCommand onStartCommand()} must be one of the following
+constants:</p>
+
+<dl>
+ <dt>{@link android.app.Service#START_NOT_STICKY}</dt>
+ <dd>If the system kills the service after {@link android.app.Service#onStartCommand
+onStartCommand()} returns, <em>do not</em> recreate the service, unless there are pending
+intents to deliver. This is the safest option to avoid running your service when not necessary
+and when your application can simply restart any unfinished jobs.</dd>
+ <dt>{@link android.app.Service#START_STICKY}</dt>
+ <dd>If the system kills the service after {@link android.app.Service#onStartCommand
+onStartCommand()} returns, recreate the service and call {@link
+android.app.Service#onStartCommand onStartCommand()}, but <em>do not</em> redeliver the last intent.
+Instead, the system calls {@link android.app.Service#onStartCommand onStartCommand()} with a
+null intent, unless there were pending intents to start the service, in which case,
+those intents are delivered. This is suitable for media players (or similar services) that are not
+executing commands, but running indefinitely and waiting for a job.</dd>
+ <dt>{@link android.app.Service#START_REDELIVER_INTENT}</dt>
+ <dd>If the system kills the service after {@link android.app.Service#onStartCommand
+onStartCommand()} returns, recreate the service and call {@link
+android.app.Service#onStartCommand onStartCommand()} with the last intent that was delivered to the
+service. Any pending intents are delivered in turn. This is suitable for services that are
+actively performing a job that should be immediately resumed, such as downloading a file.</dd>
+</dl>
+<p>For more details about these return values, see the linked reference documentation for each
+constant.</p>
+
+
+
+<h3 id="StartingAService">Starting a Service</h3>
+
+<p>You can start a service from an activity or other application component by passing an
+{@link android.content.Intent} (specifying the service to start) to {@link
+android.content.Context#startService startService()}. The Android system calls the service's {@link
+android.app.Service#onStartCommand onStartCommand()} method and passes it the {@link
+android.content.Intent}. (You should never call {@link android.app.Service#onStartCommand
+onStartCommand()} directly.)</p>
+
+<p>For example, an activity can start the example service in the previous section ({@code
+HelloSevice}) using an explicit intent with {@link android.content.Context#startService
+startService()}:</p>
+
+<pre>
+Intent intent = new Intent(this, HelloService.class);
+startService(intent);
+</pre>
+
+<p>The {@link android.content.Context#startService startService()} method returns immediately and
+the Android system calls the service's {@link android.app.Service#onStartCommand
+onStartCommand()} method. If the service is not already running, the system first calls {@link
+android.app.Service#onCreate onCreate()}, then calls {@link android.app.Service#onStartCommand
+onStartCommand()}.</p>
+
+<p>If the service does not also provide binding, the intent delivered with {@link
+android.content.Context#startService startService()} is the only mode of communication between the
+application component and the service. However, if you want the service to send a result back, then
+the client that starts the service can create a {@link android.app.PendingIntent} for a broadcast
+(with {@link android.app.PendingIntent#getBroadcast getBroadcast()}) and deliver it to the service
+in the {@link android.content.Intent} that starts the service. The service can then use the
+broadcast to deliver a result.</p>
+
+<p>Multiple requests to start the service result in multiple corresponding calls to the service's
+{@link android.app.Service#onStartCommand onStartCommand()}. However, only one request to stop
+the service (with {@link android.app.Service#stopSelf stopSelf()} or {@link
+android.content.Context#stopService stopService()}) is required to stop it.</p>
+
+
+<h3 id="Stopping">Stopping a service</h3>
+
+<p>A started service must manage its own lifecycle. That is, the system does not stop or
+destroy the service unless it must recover system memory and the service
+continues to run after {@link android.app.Service#onStartCommand onStartCommand()} returns. So,
+the service must stop itself by calling {@link android.app.Service#stopSelf stopSelf()} or another
+component can stop it by calling {@link android.content.Context#stopService stopService()}.</p>
+
+<p>Once requested to stop with {@link android.app.Service#stopSelf stopSelf()} or {@link
+android.content.Context#stopService stopService()}, the system destroys the service as soon as
+possible.</p>
+
+<p>However, if your service handles multiple requests to {@link
+android.app.Service#onStartCommand onStartCommand()} concurrently, then you shouldn't stop the
+service when you're done processing a start request, because you might have since received a new
+start request (stopping at the end of the first request would terminate the second one). To avoid
+this problem, you can use {@link android.app.Service#stopSelf(int)} to ensure that your request to
+stop the service is always based on the most recent start request. That is, when you call {@link
+android.app.Service#stopSelf(int)}, you pass the ID of the start request (the <code>startId</code>
+delivered to {@link android.app.Service#onStartCommand onStartCommand()}) to which your stop request
+corresponds. Then if the service received a new start request before you were able to call {@link
+android.app.Service#stopSelf(int)}, then the ID will not match and the service will not stop.</p>
+
+<p class="caution"><strong>Caution:</strong> It's important that your application stops its services
+when it's done working, to avoid wasting system resources and consuming battery power. If necessary,
+other components can stop the service by calling {@link
+android.content.Context#stopService stopService()}. Even if you enable binding for the service,
+you must always stop the service yourself if it ever received a call to {@link
+android.app.Service#onStartCommand onStartCommand()}.</p>
+
+<p>For more information about the lifecycle of a service, see the section below about <a
+href="#Lifecycle">Managing the Lifecycle of a Service</a>.</p>
+
+
+
+<h2 id="CreatingBoundService">Creating a Bound Service</h2>
+
+<p>A bound service is one that allows application components to bind to it by calling {@link
+android.content.Context#bindService bindService()} in order to create a long-standing connection
+(and generally does not allow components to <em>start</em> it by calling {@link
+android.content.Context#startService startService()}).</p>
+
+<p>You should create a bound service when you want to interact with the service from activities
+and other components in your application or to expose some of your application's functionality to
+other applications, through interprocess communication (IPC).</p>
+
+<p>To create a bound service, you must implement the {@link
+android.app.Service#onBind onBind()} callback method to return an {@link android.os.IBinder} that
+defines the interface for communication with the service. Other application components can then call
+{@link android.content.Context#bindService bindService()} to retrieve the interface and
+begin calling methods on the service. The service lives only to serve the application component that
+is bound to it, so when there are no components bound to the service, the system destroys it
+(you do <em>not</em> need to stop a bound service in the way you must when the service is started
+through {@link android.app.Service#onStartCommand onStartCommand()}).</p>
+
+<p>To create a bound service, the first thing you must do is define the interface that specifies
+how a client can communicate with the service. This interface between the service
+and a client must be an implementation of {@link android.os.IBinder} and is what your service must
+return from the {@link android.app.Service#onBind
+onBind()} callback method. Once the client receives the {@link android.os.IBinder}, it can begin
+interacting with the service through that interface.</p>
+
+<p>Multiple clients can bind to the service at once. When a client is done interacting with the
+service, it calls {@link android.content.Context#unbindService unbindService()} to unbind. Once
+there are no clients bound to the service, the system destroys the service.</p>
+
+<p>There are multiple ways to implement a bound service and the implementation is more
+complicated than a started service, so the bound service discussion appears in a separate
+document about <a
+href="{@docRoot}guide/topics/fundamentals/bound-services.html">Bound Services</a>.</p>
+
+
+
+<h2 id="Notifications">Sending Notifications to the User</h2>
+
+<p>Once running, a service can notify the user of events using <a
+href="{@docRoot}guide/topics/ui/notifiers/toasts.html">Toast Notifications</a> or <a
+href="{@docRoot}guide/topics/ui/notifiers/notifications.html">Status Bar Notifications</a>.</p>
+
+<p>A toast notification is a message that appears on the surface of the current window for a
+moment then disappears, while a status bar notification provides an icon in the status bar with a
+message, which the user can select in order to take an action (such as start an activity).</p>
+
+<p>Usually, a status bar notification is the best technique when some background work has completed
+(such as a file completed
+downloading) and the user can now act on it. When the user selects the notification from the
+expanded view, the notification can start an activity (such as to view the downloaded file).</p>
+
+<p>See the <a
+href="{@docRoot}guide/topics/ui/notifiers/toasts.html">Toast Notifications</a> or <a
+href="{@docRoot}guide/topics/ui/notifiers/notifications.html">Status Bar Notifications</a>
+developer guides for more information.</p>
+
+
+
+<h2 id="Foreground">Running a Service in the Foreground</h2>
+
+<p>A foreground service is a service that's considered to be something the
+user is actively aware of and thus not a candidate for the system to kill when low on memory. A
+foreground service must provide a notification for the status bar, which is placed under the
+"Ongoing" heading, which means that the notification cannot be dismissed unless the service is
+either stopped or removed from the foreground.</p>
+
+<p>For example, a music player that plays music from a service should be set to run in the
+foreground, because the user it explicitly aware
+of its operation. The notification in the status bar might indicate the current song and allow
+the user to launch an activity to interact with the music player.</p>
+
+<p>To request that your service run in the foreground, call {@link
+android.app.Service#startForeground startForeground()}. This method takes two parameters: an integer
+that uniquely identifies the notification and the {@link
+android.app.Notification} for the status bar. For example:</p>
+
+<pre>
+Notification notification = new Notification(R.drawable.icon, getText(R.string.ticker_text),
+ System.currentTimeMillis());
+Intent notificationIntent = new Intent(this, ExampleActivity.class);
+PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
+notification.setLatestEventInfo(this, getText(R.string.notification_title),
+ getText(R.string.notification_message), pendingIntent);
+startForeground(ONGOING_NOTIFICATION, notification);
+</pre>
+
+
+<p>To remove the service from the foreground, call {@link
+android.app.Service#stopForeground stopForeground()}. This method takes a boolean, indicating
+whether to remove the status bar notification as well. This method does <em>not</em> stop the
+service. However, if you stop the service while it's still running in the foreground, then the
+notification is also removed.</p>
+
+<p class="note"><strong>Note:</strong> The methods {@link
+android.app.Service#startForeground startForeground()} and {@link
+android.app.Service#stopForeground stopForeground()} were introduced in Android 2.0 (API Level
+5). In order to run your service in the foreground on older versions of the platform, you must
+use the previous {@code setForeground()} method&mdash;see the {@link
+android.app.Service#startForeground startForeground()} documentation for information about how
+to provide backward compatibility.</p>
+
+<p>For more information about notifications, see <a
+href="{@docRoot}guide/topics/ui/notifiers/notifications.html">Creating Status Bar
+Notifications</a>.</p>
+
+
+
+<h2 id="Lifecycle">Managing the Lifecycle of a Service</h2>
+
+<p>The lifecycle of a service is much simpler than that of an activity. However, it's even more important
+that you pay close attention to how your service is created and destroyed, because a service
+can run in the background without the user being aware.</p>
+
+<p>The service lifecycle&mdash;from when it's created to when it's destroyed&mdash;can follow two
+different paths:</p>
+
+<ul>
+<li>A started service
+ <p>The service is created when another component calls {@link
+android.content.Context#startService startService()}. The service then runs indefinitely and must
+stop itself by calling {@link
+android.app.Service#stopSelf() stopSelf()}. Another component can also stop the
+service by calling {@link android.content.Context#stopService
+stopService()}. When the service is stopped, the system destroys it..</p></li>
+
+<li>A bound service
+ <p>The service is created when another component (a client) calls {@link
+android.content.Context#bindService bindService()}. The client then communicates with the service
+through an {@link android.os.IBinder} interface. The client can close the connection by calling
+{@link android.content.Context#unbindService unbindService()}. Multiple clients can bind to
+the same service and when all of them unbind, the system destroys the service. (The service
+does <em>not</em> need to stop itself.)</p></li>
+</ul>
+
+<p>These two paths are not entirely separate. That is, you can bind to a service that was already
+started with {@link android.content.Context#startService startService()}. For example, a background
+music service could be started by calling {@link android.content.Context#startService
+startService()} with an {@link android.content.Intent} that identifies the music to play. Later,
+possibly when the user wants to exercise some control over the player or get information about the
+current song, an activity can bind to the service by calling {@link
+android.content.Context#bindService bindService()}. In cases like this, {@link
+android.content.Context#stopService stopService()} or {@link android.app.Service#stopSelf
+stopSelf()} does not actually stop the service until all clients unbind. </p>
+
+
+<h3 id="LifecycleCallbacks">Implementing the lifecycle callbacks</h3>
+
+<p>Like an activity, a service has lifecycle callback methods that you can implement to monitor
+changes in the service's state and perform work at the appropriate times. The following skeleton
+service demonstrates each of the lifecycle methods:</p>
+
+
+<div class="figure" style="width:432px">
+<img src="{@docRoot}images/service_lifecycle.png" alt="" />
+<p class="img-caption"><strong>Figure 2.</strong> The service lifecycle. The diagram on the left
+shows the lifecycle when the service is created with {@link android.content.Context#startService
+startService()} and the diagram on the right shows the lifecycle when the service is created
+with {@link android.content.Context#bindService bindService()}.</p>
+</div>
+
+<pre>
+public class ExampleService extends Service {
+ int mStartMode; // indicates how to behave if the service is killed
+ IBinder mBinder; // interface for clients that bind
+ boolean mAllowRebind; // indicates whether onRebind should be used
+
+ &#64;Override
+ public void {@link android.app.Service#onCreate onCreate}() {
+ // The service is being created
+ }
+ &#64;Override
+ public int {@link android.app.Service#onStartCommand onStartCommand}(Intent intent, int flags, int startId) {
+ // The service is starting, due to a call to {@link android.content.Context#startService startService()}
+ return <em>mStartMode</em>;
+ }
+ &#64;Override
+ public IBinder {@link android.app.Service#onBind onBind}(Intent intent) {
+ // A client is binding to the service with {@link android.content.Context#bindService bindService()}
+ return <em>mBinder</em>;
+ }
+ &#64;Override
+ public boolean {@link android.app.Service#onUnbind onUnbind}(Intent intent) {
+ // All clients have unbound with {@link android.content.Context#unbindService unbindService()}
+ return <em>mAllowRebind</em>;
+ }
+ &#64;Override
+ public void {@link android.app.Service#onRebind onRebind}(Intent intent) {
+ // A client is binding to the service with {@link android.content.Context#bindService bindService()},
+ // after onUnbind() has already been called
+ }
+ &#64;Override
+ public void {@link android.app.Service#onDestroy onDestroy}() {
+ // The service is no longer used and is being destroyed
+ }
+}
+</pre>
+
+<p class="note"><strong>Note:</strong> Unlike the activity lifecycle callback methods, you are
+<em>not</em> required to call the superclass implementation of these callback methods.</p>
+
+<p>By implementing these methods, you can monitor two nested loops of the service's lifecycle: </p>
+
+<ul>
+<li>The <strong>entire lifetime</strong> of a service happens between the time {@link
+android.app.Service#onCreate onCreate()} is called and the time {@link
+android.app.Service#onDestroy} returns. Like an activity, a service does its initial setup in
+{@link android.app.Service#onCreate onCreate()} and releases all remaining resources in {@link
+android.app.Service#onDestroy onDestroy()}. For example, a
+music playback service could create the thread where the music will be played in {@link
+android.app.Service#onCreate onCreate()}, then stop the thread in {@link
+android.app.Service#onDestroy onDestroy()}.
+
+<p>The {@link android.app.Service#onCreate onCreate()} and {@link android.app.Service#onDestroy
+onDestroy()} methods are called for all services, whether
+they're created by {@link android.content.Context#startService startService()} or {@link
+android.content.Context#bindService bindService()}.</p></li>
+
+<li>The <strong>active lifetime</strong> of a service begins with a call to either {@link
+android.app.Service#onStartCommand onStartCommand()} or {@link android.app.Service#onBind onBind()}.
+Each method is handed the {@link
+android.content.Intent} that was passed to either {@link android.content.Context#startService
+startService()} or {@link android.content.Context#bindService bindService()}, respectively.
+<p>If the service is started, the active lifetime ends the same time that the entire lifetime
+ends (the service is still active even after {@link android.app.Service#onStartCommand
+onStartCommand()} returns). If the service is bound, the active lifetime ends when {@link
+android.app.Service#onUnbind onUnbind()} returns.</p>
+</li>
+</ul>
+
+<p class="note"><strong>Note:</strong> Although a started service is stopped by a call to
+either {@link android.app.Service#stopSelf stopSelf()} or {@link
+android.content.Context#stopService stopService()}, there is not a respective callback for the
+service (there's no {@code onStop()} callback). So, unless the service is bound to a client,
+the system destroys it when the service is stopped&mdash;{@link
+android.app.Service#onDestroy onDestroy()} is the only callback received.</p>
+
+<p>Figure 2 illustrates the typical callback methods for a service. Although the figure separates
+services that are created by {@link android.content.Context#startService startService()} from those
+created by {@link android.content.Context#bindService bindService()}, keep
+in mind that any service, no matter how it's started, can potentially allow clients to bind to it.
+So, a service that was initially started with {@link android.app.Service#onStartCommand
+onStartCommand()} (by a client calling {@link android.content.Context#startService startService()})
+can still receive a call to {@link android.app.Service#onBind onBind()} (when a client calls
+{@link android.content.Context#bindService bindService()}).</p>
+
+<p>For more information about creating a service that provides binding, see the <a
+href="{@docRoot}guide/topics/fundamentals/bound-services.html">Bound Services</a> document,
+which includes more information about the {@link android.app.Service#onRebind onRebind()}
+callback method in the section about <a
+href="{@docRoot}guide/topics/fundamentals/bound-services.html#Lifecycle">Managing the Lifecycle of
+a Bound Service</a>.</p>
+
+
+
+<h2>Beginner's Path</h2>
+
+<p>To learn how to query data from the system or other applications (such as contacts or media
+stored on the device), continue with the <b><a
+href="{@docRoot}guide/topics/providers/content-providers.html">Content Providers</a></b>
+document.</p>
diff --git a/docs/html/images/fundamentals/service_binding_tree_lifecycle.png b/docs/html/images/fundamentals/service_binding_tree_lifecycle.png
new file mode 100644
index 000000000000..46d2df50e85a
--- /dev/null
+++ b/docs/html/images/fundamentals/service_binding_tree_lifecycle.png
Binary files differ
diff --git a/docs/html/images/service_lifecycle.png b/docs/html/images/service_lifecycle.png
index 0748db280183..f9602f84a93a 100644
--- a/docs/html/images/service_lifecycle.png
+++ b/docs/html/images/service_lifecycle.png
Binary files differ
diff --git a/graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java b/graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java
index 39a7dd2c492e..94a848800906 100644
--- a/graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java
@@ -207,7 +207,7 @@ public class AnimatedRotateDrawable extends Drawable implements Drawable.Callbac
@Override
public ConstantState getConstantState() {
if (mState.canConstantState()) {
- mState.mChangingConfigurations = super.getChangingConfigurations();
+ mState.mChangingConfigurations = getChangingConfigurations();
return mState;
}
return null;
diff --git a/graphics/java/android/graphics/drawable/BitmapDrawable.java b/graphics/java/android/graphics/drawable/BitmapDrawable.java
index 032244f35c83..2c09ddca2b9c 100644
--- a/graphics/java/android/graphics/drawable/BitmapDrawable.java
+++ b/graphics/java/android/graphics/drawable/BitmapDrawable.java
@@ -439,7 +439,7 @@ public class BitmapDrawable extends Drawable {
@Override
public final ConstantState getConstantState() {
- mBitmapState.mChangingConfigurations = super.getChangingConfigurations();
+ mBitmapState.mChangingConfigurations = getChangingConfigurations();
return mBitmapState;
}
diff --git a/graphics/java/android/graphics/drawable/ClipDrawable.java b/graphics/java/android/graphics/drawable/ClipDrawable.java
index 0d4459141f09..b333e0165143 100644
--- a/graphics/java/android/graphics/drawable/ClipDrawable.java
+++ b/graphics/java/android/graphics/drawable/ClipDrawable.java
@@ -232,7 +232,7 @@ public class ClipDrawable extends Drawable implements Drawable.Callback {
@Override
public ConstantState getConstantState() {
if (mClipState.canConstantState()) {
- mClipState.mChangingConfigurations = super.getChangingConfigurations();
+ mClipState.mChangingConfigurations = getChangingConfigurations();
return mClipState;
}
return null;
diff --git a/graphics/java/android/graphics/drawable/ColorDrawable.java b/graphics/java/android/graphics/drawable/ColorDrawable.java
index 4d560bea3f03..4418e02a89f5 100644
--- a/graphics/java/android/graphics/drawable/ColorDrawable.java
+++ b/graphics/java/android/graphics/drawable/ColorDrawable.java
@@ -149,7 +149,7 @@ public class ColorDrawable extends Drawable {
@Override
public ConstantState getConstantState() {
- mState.mChangingConfigurations = super.getChangingConfigurations();
+ mState.mChangingConfigurations = getChangingConfigurations();
return mState;
}
diff --git a/graphics/java/android/graphics/drawable/DrawableContainer.java b/graphics/java/android/graphics/drawable/DrawableContainer.java
index 0a580eb5f41c..a9414e800e69 100644
--- a/graphics/java/android/graphics/drawable/DrawableContainer.java
+++ b/graphics/java/android/graphics/drawable/DrawableContainer.java
@@ -389,7 +389,7 @@ public class DrawableContainer extends Drawable implements Drawable.Callback {
@Override
public ConstantState getConstantState() {
if (mDrawableContainerState.canConstantState()) {
- mDrawableContainerState.mChangingConfigurations = super.getChangingConfigurations();
+ mDrawableContainerState.mChangingConfigurations = getChangingConfigurations();
return mDrawableContainerState;
}
return null;
diff --git a/graphics/java/android/graphics/drawable/GradientDrawable.java b/graphics/java/android/graphics/drawable/GradientDrawable.java
index da8bb1b1a80b..65c6ccfa25d7 100644
--- a/graphics/java/android/graphics/drawable/GradientDrawable.java
+++ b/graphics/java/android/graphics/drawable/GradientDrawable.java
@@ -861,7 +861,7 @@ public class GradientDrawable extends Drawable {
@Override
public ConstantState getConstantState() {
- mGradientState.mChangingConfigurations = super.getChangingConfigurations();
+ mGradientState.mChangingConfigurations = getChangingConfigurations();
return mGradientState;
}
diff --git a/graphics/java/android/graphics/drawable/InsetDrawable.java b/graphics/java/android/graphics/drawable/InsetDrawable.java
index 3a74dfdbfd60..231234cf4ee7 100644
--- a/graphics/java/android/graphics/drawable/InsetDrawable.java
+++ b/graphics/java/android/graphics/drawable/InsetDrawable.java
@@ -241,7 +241,7 @@ public class InsetDrawable extends Drawable implements Drawable.Callback
@Override
public ConstantState getConstantState() {
if (mInsetState.canConstantState()) {
- mInsetState.mChangingConfigurations = super.getChangingConfigurations();
+ mInsetState.mChangingConfigurations = getChangingConfigurations();
return mInsetState;
}
return null;
diff --git a/graphics/java/android/graphics/drawable/LayerDrawable.java b/graphics/java/android/graphics/drawable/LayerDrawable.java
index 84da1706ad5e..49dbbca5a6f3 100644
--- a/graphics/java/android/graphics/drawable/LayerDrawable.java
+++ b/graphics/java/android/graphics/drawable/LayerDrawable.java
@@ -557,7 +557,7 @@ public class LayerDrawable extends Drawable implements Drawable.Callback {
@Override
public ConstantState getConstantState() {
if (mLayerState.canConstantState()) {
- mLayerState.mChangingConfigurations = super.getChangingConfigurations();
+ mLayerState.mChangingConfigurations = getChangingConfigurations();
return mLayerState;
}
return null;
diff --git a/graphics/java/android/graphics/drawable/NinePatchDrawable.java b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
index 35b831928de5..a5175c5526a3 100644
--- a/graphics/java/android/graphics/drawable/NinePatchDrawable.java
+++ b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
@@ -323,7 +323,7 @@ public class NinePatchDrawable extends Drawable {
@Override
public ConstantState getConstantState() {
- mNinePatchState.mChangingConfigurations = super.getChangingConfigurations();
+ mNinePatchState.mChangingConfigurations = getChangingConfigurations();
return mNinePatchState;
}
diff --git a/graphics/java/android/graphics/drawable/RotateDrawable.java b/graphics/java/android/graphics/drawable/RotateDrawable.java
index 212ddfac629d..4f74b374cbdb 100644
--- a/graphics/java/android/graphics/drawable/RotateDrawable.java
+++ b/graphics/java/android/graphics/drawable/RotateDrawable.java
@@ -192,7 +192,7 @@ public class RotateDrawable extends Drawable implements Drawable.Callback {
@Override
public ConstantState getConstantState() {
if (mState.canConstantState()) {
- mState.mChangingConfigurations = super.getChangingConfigurations();
+ mState.mChangingConfigurations = getChangingConfigurations();
return mState;
}
return null;
diff --git a/graphics/java/android/graphics/drawable/ScaleDrawable.java b/graphics/java/android/graphics/drawable/ScaleDrawable.java
index 055576dc89b9..a7ed0d0a14b5 100644
--- a/graphics/java/android/graphics/drawable/ScaleDrawable.java
+++ b/graphics/java/android/graphics/drawable/ScaleDrawable.java
@@ -241,7 +241,7 @@ public class ScaleDrawable extends Drawable implements Drawable.Callback {
@Override
public ConstantState getConstantState() {
if (mScaleState.canConstantState()) {
- mScaleState.mChangingConfigurations = super.getChangingConfigurations();
+ mScaleState.mChangingConfigurations = getChangingConfigurations();
return mScaleState;
}
return null;
diff --git a/graphics/java/android/graphics/drawable/ShapeDrawable.java b/graphics/java/android/graphics/drawable/ShapeDrawable.java
index 92252fc06001..cb8774ddf874 100644
--- a/graphics/java/android/graphics/drawable/ShapeDrawable.java
+++ b/graphics/java/android/graphics/drawable/ShapeDrawable.java
@@ -356,7 +356,7 @@ public class ShapeDrawable extends Drawable {
@Override
public ConstantState getConstantState() {
- mShapeState.mChangingConfigurations = super.getChangingConfigurations();
+ mShapeState.mChangingConfigurations = getChangingConfigurations();
return mShapeState;
}
diff --git a/graphics/java/android/renderscript/Program.java b/graphics/java/android/renderscript/Program.java
index fdd138ca72b9..323225f6f5a4 100644
--- a/graphics/java/android/renderscript/Program.java
+++ b/graphics/java/android/renderscript/Program.java
@@ -33,10 +33,10 @@ import android.util.Log;
*
**/
public class Program extends BaseObj {
- public static final int MAX_INPUT = 8;
- public static final int MAX_OUTPUT = 8;
- public static final int MAX_CONSTANT = 8;
- public static final int MAX_TEXTURE = 8;
+ static final int MAX_INPUT = 8;
+ static final int MAX_OUTPUT = 8;
+ static final int MAX_CONSTANT = 8;
+ static final int MAX_TEXTURE = 8;
/**
*
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index 75b16713c761..e3593daeee07 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -128,10 +128,10 @@ DisplayList::~DisplayList() {
}
mBitmapResources.clear();
- for (size_t i = 0; i < mShaderResources.size(); i++) {
- caches.resourceCache.decrementRefcount(mShaderResources.itemAt(i));
+ for (size_t i = 0; i < mShaders.size(); i++) {
+ caches.resourceCache.decrementRefcount(mShaders.itemAt(i));
}
- mShaderResources.clear();
+ mShaders.clear();
for (size_t i = 0; i < mPaints.size(); i++) {
delete mPaints.itemAt(i);
@@ -179,11 +179,11 @@ void DisplayList::initFromDisplayListRenderer(const DisplayListRenderer& recorde
caches.resourceCache.incrementRefcount(resource);
}
- const Vector<SkiaShader*> &shaderResources = recorder.getShaderResources();
- for (size_t i = 0; i < shaderResources.size(); i++) {
- SkiaShader* resource = shaderResources.itemAt(i);
- mShaderResources.add(resource);
- caches.resourceCache.incrementRefcount(resource);
+ const Vector<SkiaShader*> &shaders = recorder.getShaders();
+ for (size_t i = 0; i < shaders.size(); i++) {
+ SkiaShader* shader = shaders.itemAt(i);
+ mShaders.add(shader);
+ caches.resourceCache.incrementRefcount(shader);
}
const Vector<SkPaint*> &paints = recorder.getPaints();
@@ -407,11 +407,11 @@ void DisplayListRenderer::reset() {
}
mBitmapResources.clear();
- for (size_t i = 0; i < mShaderResources.size(); i++) {
- SkiaShader* resource = mShaderResources.itemAt(i);
- caches.resourceCache.decrementRefcount(resource);
+ for (size_t i = 0; i < mShaders.size(); i++) {
+ caches.resourceCache.decrementRefcount(mShaders.itemAt(i));
}
- mShaderResources.clear();
+ mShaders.clear();
+ mShaderMap.clear();
mPaints.clear();
mPaintMap.clear();
diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h
index cc5230942e30..71523349f0d3 100644
--- a/libs/hwui/DisplayListRenderer.h
+++ b/libs/hwui/DisplayListRenderer.h
@@ -206,11 +206,11 @@ private:
PathHeap* mPathHeap;
Vector<SkBitmap*> mBitmapResources;
- Vector<SkiaShader*> mShaderResources;
Vector<SkiaColorFilter*> mFilterResources;
Vector<SkPaint*> mPaints;
Vector<SkMatrix*> mMatrices;
+ Vector<SkiaShader*> mShaders;
mutable SkFlattenableReadBuffer mReader;
@@ -291,8 +291,8 @@ public:
return mBitmapResources;
}
- const Vector<SkiaShader*>& getShaderResources() const {
- return mShaderResources;
+ const Vector<SkiaShader*>& getShaders() const {
+ return mShaders;
}
const Vector<SkPaint*>& getPaints() const {
@@ -366,12 +366,12 @@ private:
}
inline void addPaint(SkPaint* paint) {
- if (paint == NULL) {
+ if (!paint) {
addInt((int) NULL);
return;
}
- SkPaint *paintCopy = mPaintMap.valueFor(paint);
+ SkPaint* paintCopy = mPaintMap.valueFor(paint);
if (paintCopy == NULL || paintCopy->getGenerationID() != paint->getGenerationID()) {
paintCopy = new SkPaint(*paint);
mPaintMap.add(paint, paintCopy);
@@ -406,10 +406,21 @@ private:
}
inline void addShader(SkiaShader* shader) {
- addInt((int) shader);
- mShaderResources.add(shader);
- Caches& caches = Caches::getInstance();
- caches.resourceCache.incrementRefcount(shader);
+ if (!shader) {
+ addInt((int) NULL);
+ return;
+ }
+
+ SkiaShader* shaderCopy = mShaderMap.valueFor(shader);
+ // TODO: We also need to handle generation ID changes in compose shaders
+ if (shaderCopy == NULL || shaderCopy->getGenerationId() != shader->getGenerationId()) {
+ shaderCopy = shader->copy();
+ mShaderMap.add(shader, shaderCopy);
+ mShaders.add(shaderCopy);
+ Caches::getInstance().resourceCache.incrementRefcount(shaderCopy);
+ }
+
+ addInt((int) shaderCopy);
}
inline void addColorFilter(SkiaColorFilter* colorFilter) {
@@ -422,11 +433,14 @@ private:
SkChunkAlloc mHeap;
Vector<SkBitmap*> mBitmapResources;
- Vector<SkiaShader*> mShaderResources;
Vector<SkiaColorFilter*> mFilterResources;
Vector<SkPaint*> mPaints;
DefaultKeyedVector<SkPaint*, SkPaint*> mPaintMap;
+
+ Vector<SkiaShader*> mShaders;
+ DefaultKeyedVector<SkiaShader*, SkiaShader*> mShaderMap;
+
Vector<SkMatrix*> mMatrices;
PathHeap* mPathHeap;
diff --git a/libs/hwui/ResourceCache.cpp b/libs/hwui/ResourceCache.cpp
index 00de39b3068b..70d117a3622b 100644
--- a/libs/hwui/ResourceCache.cpp
+++ b/libs/hwui/ResourceCache.cpp
@@ -67,12 +67,12 @@ void ResourceCache::incrementRefcount(SkBitmap* bitmapResource) {
void ResourceCache::incrementRefcount(SkiaShader* shaderResource) {
shaderResource->getSkShader()->safeRef();
- incrementRefcount((void*)shaderResource, kShader);
+ incrementRefcount((void*) shaderResource, kShader);
}
void ResourceCache::incrementRefcount(SkiaColorFilter* filterResource) {
filterResource->getSkColorFilter()->safeRef();
- incrementRefcount((void*)filterResource, kColorFilter);
+ incrementRefcount((void*) filterResource, kColorFilter);
}
void ResourceCache::decrementRefcount(void* resource) {
@@ -91,17 +91,17 @@ void ResourceCache::decrementRefcount(void* resource) {
void ResourceCache::decrementRefcount(SkBitmap* bitmapResource) {
bitmapResource->pixelRef()->safeUnref();
bitmapResource->getColorTable()->safeUnref();
- decrementRefcount((void*)bitmapResource);
+ decrementRefcount((void*) bitmapResource);
}
void ResourceCache::decrementRefcount(SkiaShader* shaderResource) {
shaderResource->getSkShader()->safeUnref();
- decrementRefcount((void*)shaderResource);
+ decrementRefcount((void*) shaderResource);
}
void ResourceCache::decrementRefcount(SkiaColorFilter* filterResource) {
filterResource->getSkColorFilter()->safeUnref();
- decrementRefcount((void*)filterResource);
+ decrementRefcount((void*) filterResource);
}
void ResourceCache::recycle(SkBitmap* resource) {
diff --git a/libs/hwui/SkiaShader.cpp b/libs/hwui/SkiaShader.cpp
index 590a9d7c41b8..8878c709809e 100644
--- a/libs/hwui/SkiaShader.cpp
+++ b/libs/hwui/SkiaShader.cpp
@@ -47,10 +47,22 @@ static const GLint gTileModes[] = {
// Base shader
///////////////////////////////////////////////////////////////////////////////
+void SkiaShader::copyFrom(const SkiaShader& shader) {
+ mType = shader.mType;
+ mKey = shader.mKey;
+ mTileX = shader.mTileX;
+ mTileY = shader.mTileY;
+ mBlend = shader.mBlend;
+ mUnitMatrix = shader.mUnitMatrix;
+ mShaderMatrix = shader.mShaderMatrix;
+ mGenerationId = shader.mGenerationId;
+}
+
SkiaShader::SkiaShader(Type type, SkShader* key, SkShader::TileMode tileX,
SkShader::TileMode tileY, SkMatrix* matrix, bool blend):
mType(type), mKey(key), mTileX(tileX), mTileY(tileY), mBlend(blend) {
setMatrix(matrix);
+ mGenerationId = 0;
}
SkiaShader::~SkiaShader() {
@@ -90,6 +102,13 @@ SkiaBitmapShader::SkiaBitmapShader(SkBitmap* bitmap, SkShader* key, SkShader::Ti
updateLocalMatrix(matrix);
}
+SkiaShader* SkiaBitmapShader::copy() {
+ SkiaBitmapShader* copy = new SkiaBitmapShader();
+ copy->copyFrom(*this);
+ copy->mBitmap = mBitmap;
+ return copy;
+}
+
void SkiaBitmapShader::describe(ProgramDescription& description, const Extensions& extensions) {
Texture* texture = mTextureCache->get(mBitmap);
if (!texture) return;
@@ -183,6 +202,19 @@ SkiaLinearGradientShader::~SkiaLinearGradientShader() {
delete[] mPositions;
}
+SkiaShader* SkiaLinearGradientShader::copy() {
+ SkiaLinearGradientShader* copy = new SkiaLinearGradientShader();
+ copy->copyFrom(*this);
+ copy->mBounds = new float[4];
+ memcpy(copy->mBounds, mBounds, sizeof(float) * 4);
+ copy->mColors = new uint32_t[mCount];
+ memcpy(copy->mColors, mColors, sizeof(uint32_t) * mCount);
+ copy->mPositions = new float[mCount];
+ memcpy(copy->mPositions, mPositions, sizeof(float) * mCount);
+ copy->mCount = mCount;
+ return copy;
+}
+
void SkiaLinearGradientShader::describe(ProgramDescription& description,
const Extensions& extensions) {
description.hasGradient = true;
@@ -238,6 +270,17 @@ SkiaCircularGradientShader::SkiaCircularGradientShader(float x, float y, float r
updateLocalMatrix(matrix);
}
+SkiaShader* SkiaCircularGradientShader::copy() {
+ SkiaCircularGradientShader* copy = new SkiaCircularGradientShader();
+ copy->copyFrom(*this);
+ copy->mColors = new uint32_t[mCount];
+ memcpy(copy->mColors, mColors, sizeof(uint32_t) * mCount);
+ copy->mPositions = new float[mCount];
+ memcpy(copy->mPositions, mPositions, sizeof(float) * mCount);
+ copy->mCount = mCount;
+ return copy;
+}
+
void SkiaCircularGradientShader::describe(ProgramDescription& description,
const Extensions& extensions) {
description.hasGradient = true;
@@ -276,6 +319,17 @@ SkiaSweepGradientShader::~SkiaSweepGradientShader() {
delete[] mPositions;
}
+SkiaShader* SkiaSweepGradientShader::copy() {
+ SkiaSweepGradientShader* copy = new SkiaSweepGradientShader();
+ copy->copyFrom(*this);
+ copy->mColors = new uint32_t[mCount];
+ memcpy(copy->mColors, mColors, sizeof(uint32_t) * mCount);
+ copy->mPositions = new float[mCount];
+ memcpy(copy->mPositions, mPositions, sizeof(float) * mCount);
+ copy->mCount = mCount;
+ return copy;
+}
+
void SkiaSweepGradientShader::describe(ProgramDescription& description,
const Extensions& extensions) {
description.hasGradient = true;
@@ -315,7 +369,25 @@ void SkiaSweepGradientShader::updateTransforms(Program* program, const mat4& mod
SkiaComposeShader::SkiaComposeShader(SkiaShader* first, SkiaShader* second,
SkXfermode::Mode mode, SkShader* key):
SkiaShader(kCompose, key, SkShader::kClamp_TileMode, SkShader::kClamp_TileMode,
- NULL, first->blend() || second->blend()), mFirst(first), mSecond(second), mMode(mode) {
+ NULL, first->blend() || second->blend()),
+ mFirst(first), mSecond(second), mMode(mode), mCleanup(false) {
+}
+
+SkiaComposeShader::~SkiaComposeShader() {
+ if (mCleanup) {
+ delete mFirst;
+ delete mSecond;
+ }
+}
+
+SkiaShader* SkiaComposeShader::copy() {
+ SkiaComposeShader* copy = new SkiaComposeShader();
+ copy->copyFrom(*this);
+ copy->mFirst = mFirst->copy();
+ copy->mSecond = mSecond->copy();
+ copy->mMode = mMode;
+ copy->cleanup();
+ return copy;
}
void SkiaComposeShader::set(TextureCache* textureCache, GradientCache* gradientCache) {
diff --git a/libs/hwui/SkiaShader.h b/libs/hwui/SkiaShader.h
index 6702129ad297..89dd131f8ab2 100644
--- a/libs/hwui/SkiaShader.h
+++ b/libs/hwui/SkiaShader.h
@@ -56,6 +56,9 @@ struct SkiaShader {
SkMatrix* matrix, bool blend);
virtual ~SkiaShader();
+ virtual SkiaShader* copy() = 0;
+ void copyFrom(const SkiaShader& shader);
+
virtual void describe(ProgramDescription& description, const Extensions& extensions);
virtual void setupProgram(Program* program, const mat4& modelView, const Snapshot& snapshot,
GLuint* textureUnit);
@@ -81,8 +84,13 @@ struct SkiaShader {
const Snapshot& snapshot) {
}
+ uint32_t getGenerationId() {
+ return mGenerationId;
+ }
+
void setMatrix(SkMatrix* matrix) {
updateLocalMatrix(matrix);
+ mGenerationId++;
}
void updateLocalMatrix(const SkMatrix* matrix) {
@@ -97,6 +105,9 @@ struct SkiaShader {
void computeScreenSpaceMatrix(mat4& screenSpace, const mat4& modelView);
protected:
+ SkiaShader() {
+ }
+
/**
* The appropriate texture unit must have been activated prior to invoking
* this method.
@@ -114,6 +125,9 @@ protected:
mat4 mUnitMatrix;
mat4 mShaderMatrix;
+
+private:
+ uint32_t mGenerationId;
}; // struct SkiaShader
@@ -127,6 +141,7 @@ protected:
struct SkiaBitmapShader: public SkiaShader {
SkiaBitmapShader(SkBitmap* bitmap, SkShader* key, SkShader::TileMode tileX,
SkShader::TileMode tileY, SkMatrix* matrix, bool blend);
+ SkiaShader* copy();
void describe(ProgramDescription& description, const Extensions& extensions);
void setupProgram(Program* program, const mat4& modelView, const Snapshot& snapshot,
@@ -134,6 +149,9 @@ struct SkiaBitmapShader: public SkiaShader {
void updateTransforms(Program* program, const mat4& modelView, const Snapshot& snapshot);
private:
+ SkiaBitmapShader() {
+ }
+
/**
* This method does not work for n == 0.
*/
@@ -154,6 +172,7 @@ struct SkiaLinearGradientShader: public SkiaShader {
SkiaLinearGradientShader(float* bounds, uint32_t* colors, float* positions, int count,
SkShader* key, SkShader::TileMode tileMode, SkMatrix* matrix, bool blend);
~SkiaLinearGradientShader();
+ SkiaShader* copy();
void describe(ProgramDescription& description, const Extensions& extensions);
void setupProgram(Program* program, const mat4& modelView, const Snapshot& snapshot,
@@ -161,6 +180,9 @@ struct SkiaLinearGradientShader: public SkiaShader {
void updateTransforms(Program* program, const mat4& modelView, const Snapshot& snapshot);
private:
+ SkiaLinearGradientShader() {
+ }
+
float* mBounds;
uint32_t* mColors;
float* mPositions;
@@ -174,6 +196,7 @@ struct SkiaSweepGradientShader: public SkiaShader {
SkiaSweepGradientShader(float x, float y, uint32_t* colors, float* positions, int count,
SkShader* key, SkMatrix* matrix, bool blend);
~SkiaSweepGradientShader();
+ SkiaShader* copy();
virtual void describe(ProgramDescription& description, const Extensions& extensions);
void setupProgram(Program* program, const mat4& modelView, const Snapshot& snapshot,
@@ -183,6 +206,8 @@ struct SkiaSweepGradientShader: public SkiaShader {
protected:
SkiaSweepGradientShader(Type type, float x, float y, uint32_t* colors, float* positions,
int count, SkShader* key, SkShader::TileMode tileMode, SkMatrix* matrix, bool blend);
+ SkiaSweepGradientShader() {
+ }
uint32_t* mColors;
float* mPositions;
@@ -195,8 +220,13 @@ protected:
struct SkiaCircularGradientShader: public SkiaSweepGradientShader {
SkiaCircularGradientShader(float x, float y, float radius, uint32_t* colors, float* positions,
int count, SkShader* key,SkShader::TileMode tileMode, SkMatrix* matrix, bool blend);
+ SkiaShader* copy();
void describe(ProgramDescription& description, const Extensions& extensions);
+
+private:
+ SkiaCircularGradientShader() {
+ }
}; // struct SkiaCircularGradientShader
/**
@@ -204,6 +234,8 @@ struct SkiaCircularGradientShader: public SkiaSweepGradientShader {
*/
struct SkiaComposeShader: public SkiaShader {
SkiaComposeShader(SkiaShader* first, SkiaShader* second, SkXfermode::Mode mode, SkShader* key);
+ ~SkiaComposeShader();
+ SkiaShader* copy();
void set(TextureCache* textureCache, GradientCache* gradientCache);
@@ -212,9 +244,18 @@ struct SkiaComposeShader: public SkiaShader {
GLuint* textureUnit);
private:
+ SkiaComposeShader(): mCleanup(false) {
+ }
+
+ void cleanup() {
+ mCleanup = true;
+ }
+
SkiaShader* mFirst;
SkiaShader* mSecond;
SkXfermode::Mode mMode;
+
+ bool mCleanup;
}; // struct SkiaComposeShader
}; // namespace uirenderer
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_ime_default.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_ime_default.png
index 499244bb681c..056e7e7225a0 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_ime_default.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_ime_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0.png
index b16e436e8d60..20ea73576e64 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1.png
index 1b6ed7434e3e..a5e9c7c4c9ba 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_fully.png
index 43e35d37fd96..0287d5a4089b 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_fully.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2.png
index 498adbb6df95..4dfbcb29c555 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_fully.png
index b7e42a00b054..b9d4cb02a1a3 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_fully.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3.png
index 959fc5c4804b..4c8ec0e1badf 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_fully.png
index f905979c4b9a..7e30894a5bbc 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_fully.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4.png
index 6e8e73c3212a..72635a51cc0c 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_fully.png
index b5799c8db67c..6f56886f0fcb 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_fully.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_flightmode.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_flightmode.png
index 7682bba8136f..118a6b4c4786 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_flightmode.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_flightmode.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_0.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_0.png
index 98e874aad97a..ecd880fc236f 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_0.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1.png
index 16268957db3e..7251b141bc69 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1_fully.png
index 3c2e2b97eab9..01135c862ed0 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1_fully.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_2.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_2.png
index 77e6ee40ae5e..794d9eddef27 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_2.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_2_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_2_fully.png
index 00d86bfd2f38..851ca41e62a3 100755
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_2_fully.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_2_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_3.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_3.png
index c2574e1486af..f16783c971dc 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_3.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_3_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_3_fully.png
index 70c030bd3d88..d217d0904ca2 100755
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_3_fully.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_3_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_4.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_4.png
index 55caecff88a0..b577ebe4fb59 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_4.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_4_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_4_fully.png
index b5326d257961..6cf482926a5b 100755
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_4_fully.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_4_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_default.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_default.png
index 25fffd654040..4bcd2be5cb86 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_default.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime_default.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime_default.png
index b6e4ebc0e519..dadb0cd3704f 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime_default.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime_pressed.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime_pressed.png
index 189a089c4545..51d7cc245d70 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime_pressed.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime_pressed.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_pressed.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_pressed.png
index ebade9217623..83a8b261bdb2 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_pressed.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_pressed.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_default.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_default.png
index 6ef71c7c60ed..cfeba3e5e7f0 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_default.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_pressed.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_pressed.png
index f6b0a17e61d8..b090b9570f02 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_pressed.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_pressed.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_ime_default.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_ime_default.png
index 259db7aa7329..e1d53bdfb106 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_ime_default.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_ime_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent_default.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent_default.png
index 246c6feeb179..1d97e0581c59 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent_default.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent_pressed.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent_pressed.png
index 34515c702d26..c9724fc9535c 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent_pressed.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent_pressed.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0.png
index 9216030a8454..39025f03bb2f 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1.png
index e529f6f98303..a1f7057ad9e5 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_fully.png
index e529f6f98303..7cc9f027678e 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_fully.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1x.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1x.png
index 02c27ee44582..25ca1246983c 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1x.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2.png
index 57558ad14382..122a47308bb6 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_fully.png
index 57558ad14382..4b126dcb523f 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_fully.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3.png
index e4425b2b1eac..828c0e23a269 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_fully.png
index e4425b2b1eac..f52d8f9c39b6 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_fully.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3g.png
index 84ac92760d18..2725ed23b875 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4.png
index 09de6b093a81..61501c16546c 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_fully.png
index 09de6b093a81..1171ffc754b6 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_fully.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_edge.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_edge.png
index 13cae40b84fa..83cb82035159 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_edge.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_edge.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_flightmode.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_flightmode.png
index 1534da3c1fd6..98c3b10aaf0a 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_flightmode.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_flightmode.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_gprs.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_gprs.png
index d0a4fd01a788..9c3c44c3d0b2 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_gprs.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_gprs.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_hsdpa.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_hsdpa.png
index 05976bd06c79..08b975a2edb9 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_hsdpa.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_hsdpa.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_roam.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_roam.png
index 2cc3cd642c06..ae9dc4044d8c 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_roam.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_roam.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_0.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_0.png
index 1c59b2add7ab..94c41a75fbe5 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_0.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_1.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_1.png
index 32e916587dc1..ac32aa619ff8 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_1.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_1_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_1_fully.png
index 32e916587dc1..9845c46ebeba 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_1_fully.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_1_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_2.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_2.png
index ea71298a2c27..34494e30c782 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_2.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_2_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_2_fully.png
index ea71298a2c27..77f4a7bd1cf9 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_2_fully.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_2_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_3.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_3.png
index 869a497dae71..a635c3c9db9a 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_3.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_3_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_3_fully.png
index 869a497dae71..c3e924084127 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_3_fully.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_3_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_4.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_4.png
index 1711c8252fa9..68ffdc94b913 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_4.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_4_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_4_fully.png
index 1711c8252fa9..93a3dc0830a0 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_4_fully.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_4_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/layout-xlarge/status_bar_notification_row.xml b/packages/SystemUI/res/layout-xlarge/status_bar_notification_row.xml
index 6b12d29c3fe1..4991a406efac 100644
--- a/packages/SystemUI/res/layout-xlarge/status_bar_notification_row.xml
+++ b/packages/SystemUI/res/layout-xlarge/status_bar_notification_row.xml
@@ -27,7 +27,7 @@
<!-- TODO: scaleType should be top-left but ImageView doesn't support that. -->
<com.android.systemui.statusbar.LatestItemView android:id="@+id/content"
- android:layout_width="wrap_content"
+ android:layout_width="match_parent"
android:layout_height="64sp"
android:layout_alignParentTop="true"
android:layout_toRightOf="@id/large_icon"
diff --git a/policy/src/com/android/internal/policy/impl/GlobalActions.java b/policy/src/com/android/internal/policy/impl/GlobalActions.java
index 1f06dcc4c6f2..5e33f0535c49 100644
--- a/policy/src/com/android/internal/policy/impl/GlobalActions.java
+++ b/policy/src/com/android/internal/policy/impl/GlobalActions.java
@@ -221,8 +221,7 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac
final AlertDialog.Builder ab = new AlertDialog.Builder(mContext);
ab.setAdapter(mAdapter, this)
- .setInverseBackgroundForced(true)
- .setTitle(R.string.global_actions);
+ .setInverseBackgroundForced(true);
final AlertDialog dialog = ab.create();
dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG);
@@ -249,6 +248,7 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac
} else {
mDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG);
}
+ mDialog.setTitle(R.string.global_actions);
}
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index f2c2b93f30c4..2a393227745c 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -2564,7 +2564,9 @@ public class PhoneWindowManager implements WindowManagerPolicy {
int sState = mWindowManager.getKeycodeState(KeyEvent.KEYCODE_S);
int dpadState = mWindowManager.getDPadKeycodeState(KeyEvent.KEYCODE_DPAD_CENTER);
int trackballState = mWindowManager.getTrackballScancodeState(BTN_MOUSE);
- mSafeMode = menuState > 0 || sState > 0 || dpadState > 0 || trackballState > 0;
+ int volumeDownState = mWindowManager.getKeycodeState(KeyEvent.KEYCODE_VOLUME_DOWN);
+ mSafeMode = menuState > 0 || sState > 0 || dpadState > 0 || trackballState > 0
+ || volumeDownState > 0;
performHapticFeedbackLw(null, mSafeMode
? HapticFeedbackConstants.SAFE_MODE_ENABLED
: HapticFeedbackConstants.SAFE_MODE_DISABLED, true);
diff --git a/services/java/com/android/server/InputManager.java b/services/java/com/android/server/InputManager.java
index 6dca52348039..06595ae503cb 100644
--- a/services/java/com/android/server/InputManager.java
+++ b/services/java/com/android/server/InputManager.java
@@ -423,7 +423,7 @@ public class InputManager {
@SuppressWarnings("unused")
public void notifyConfigurationChanged(long whenNanos) {
- mWindowManagerService.sendNewConfiguration();
+ mWindowManagerService.mInputMonitor.notifyConfigurationChanged();
}
@SuppressWarnings("unused")
diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java
index 9c80b516fd7e..2b98795f3776 100644
--- a/services/java/com/android/server/InputMethodManagerService.java
+++ b/services/java/com/android/server/InputMethodManagerService.java
@@ -490,7 +490,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
statusBar.setIconVisibility("ime", false);
// mSettings should be created before buildInputMethodListLocked
- mSettings = new InputMethodSettings(context.getContentResolver(), mMethodMap, mMethodList);
+ mSettings = new InputMethodSettings(
+ mRes, context.getContentResolver(), mMethodMap, mMethodList);
buildInputMethodListLocked(mMethodList, mMethodMap);
mSettings.enableAllIMEsIfThereIsNoEnabledIME();
@@ -575,7 +576,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
if (!allowsImplicitlySelectedSubtypes || enabledSubtypes.size() > 0) {
return enabledSubtypes;
} else {
- return getApplicableSubtypesLocked(imi.getSubtypes());
+ return getApplicableSubtypesLocked(mRes, imi.getSubtypes());
}
}
}
@@ -1680,7 +1681,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
ArrayList<String> subtypes = immis.get(i).second;
if (subtypes != null && subtypes.size() == 0) {
ArrayList<InputMethodSubtype> applicableSubtypes =
- getApplicableSubtypesLocked(imi.getSubtypes());
+ getApplicableSubtypesLocked(mRes, imi.getSubtypes());
final int numSubtypes = applicableSubtypes.size();
for (int j = 0; j < numSubtypes; ++j) {
subtypes.add(String.valueOf(applicableSubtypes.get(j).hashCode()));
@@ -1977,9 +1978,9 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
return NOT_A_SUBTYPE_ID;
}
- private ArrayList<InputMethodSubtype> getApplicableSubtypesLocked(
- List<InputMethodSubtype> subtypes) {
- final String systemLocale = mRes.getConfiguration().locale.toString();
+ private static ArrayList<InputMethodSubtype> getApplicableSubtypesLocked(
+ Resources res, List<InputMethodSubtype> subtypes) {
+ final String systemLocale = res.getConfiguration().locale.toString();
if (TextUtils.isEmpty(systemLocale)) return new ArrayList<InputMethodSubtype>();
HashMap<String, InputMethodSubtype> applicableModeAndSubtypesMap =
new HashMap<String, InputMethodSubtype>();
@@ -2013,7 +2014,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
applicableModeAndSubtypesMap.values());
if (!containsKeyboardSubtype) {
InputMethodSubtype lastResortKeyboardSubtype = findLastResortApplicableSubtypeLocked(
- subtypes, SUBTYPE_MODE_KEYBOARD, systemLocale, true);
+ res, subtypes, SUBTYPE_MODE_KEYBOARD, systemLocale, true);
if (lastResortKeyboardSubtype != null) {
applicableSubtypes.add(lastResortKeyboardSubtype);
}
@@ -2031,14 +2032,14 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
* it will return the first subtype matched with mode
* @return the most applicable subtypeId
*/
- private InputMethodSubtype findLastResortApplicableSubtypeLocked(
- List<InputMethodSubtype> subtypes, String mode, String locale,
+ private static InputMethodSubtype findLastResortApplicableSubtypeLocked(
+ Resources res, List<InputMethodSubtype> subtypes, String mode, String locale,
boolean canIgnoreLocaleAsLastResort) {
if (subtypes == null || subtypes.size() == 0) {
return null;
}
if (TextUtils.isEmpty(locale)) {
- locale = mRes.getConfiguration().locale.toString();
+ locale = res.getConfiguration().locale.toString();
}
final String language = locale.substring(0, 2);
boolean partialMatchFound = false;
@@ -2095,29 +2096,29 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
continue;
}
InputMethodSubtype subtype = null;
- final List<InputMethodSubtype> explicitlyEnabledSubtypes =
- mSettings.getEnabledInputMethodSubtypeListLocked(imi);
- // 1. Search by the current subtype's locale from explicitlyEnabledSubtypes.
+ final List<InputMethodSubtype> enabledSubtypes =
+ getEnabledInputMethodSubtypeList(imi, true);
+ // 1. Search by the current subtype's locale from enabledSubtypes.
if (mCurrentSubtype != null) {
subtype = findLastResortApplicableSubtypeLocked(
- explicitlyEnabledSubtypes, mode, mCurrentSubtype.getLocale(), false);
+ mRes, enabledSubtypes, mode, mCurrentSubtype.getLocale(), false);
}
- // 2. Search by the system locale from explicitlyEnabledSubtypes.
- // 3. Search the first enabled subtype matched with mode from explicitlyEnabledSubtypes.
+ // 2. Search by the system locale from enabledSubtypes.
+ // 3. Search the first enabled subtype matched with mode from enabledSubtypes.
if (subtype == null) {
subtype = findLastResortApplicableSubtypeLocked(
- explicitlyEnabledSubtypes, mode, null, true);
+ mRes, enabledSubtypes, mode, null, true);
}
// 4. Search by the current subtype's locale from all subtypes.
if (subtype == null && mCurrentSubtype != null) {
subtype = findLastResortApplicableSubtypeLocked(
- imi.getSubtypes(), mode, mCurrentSubtype.getLocale(), false);
+ mRes, imi.getSubtypes(), mode, mCurrentSubtype.getLocale(), false);
}
// 5. Search by the system locale from all subtypes.
// 6. Search the first enabled subtype matched with mode from all subtypes.
if (subtype == null) {
subtype = findLastResortApplicableSubtypeLocked(
- imi.getSubtypes(), mode, null, true);
+ mRes, imi.getSubtypes(), mode, null, true);
}
if (subtype != null) {
if (imiId.equals(mCurMethodId)) {
@@ -2177,8 +2178,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
// the most applicable subtype from all subtypes whose mode is
// SUBTYPE_MODE_KEYBOARD. This is an exceptional case, so we will hardcode
// the mode.
- mCurrentSubtype = findLastResortApplicableSubtypeLocked(imi.getSubtypes(),
- SUBTYPE_MODE_KEYBOARD, null, true);
+ mCurrentSubtype = findLastResortApplicableSubtypeLocked(
+ mRes, imi.getSubtypes(), SUBTYPE_MODE_KEYBOARD, null, true);
}
} else {
mCurrentSubtype =
@@ -2256,6 +2257,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
private final TextUtils.SimpleStringSplitter mSubtypeSplitter =
new TextUtils.SimpleStringSplitter(INPUT_METHOD_SUBTYPE_SEPARATER);
+ private final Resources mRes;
private final ContentResolver mResolver;
private final HashMap<String, InputMethodInfo> mMethodMap;
private final ArrayList<InputMethodInfo> mMethodList;
@@ -2275,8 +2277,9 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
}
public InputMethodSettings(
- ContentResolver resolver, HashMap<String, InputMethodInfo> methodMap,
- ArrayList<InputMethodInfo> methodList) {
+ Resources res, ContentResolver resolver,
+ HashMap<String, InputMethodInfo> methodMap, ArrayList<InputMethodInfo> methodList) {
+ mRes = res;
mResolver = resolver;
mMethodMap = methodMap;
mMethodList = methodList;
@@ -2516,8 +2519,9 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
// If imeId is empty, returns the first IME and subtype in the history
if (TextUtils.isEmpty(imeId) || imeInTheHistory.equals(imeId)) {
final String subtypeInTheHistory = imeAndSubtype.second;
- final String subtypeHashCode = getEnabledSubtypeForInputMethodAndSubtypeLocked(
- enabledImes, imeInTheHistory, subtypeInTheHistory);
+ final String subtypeHashCode =
+ getEnabledSubtypeHashCodeForInputMethodAndSubtypeLocked(
+ enabledImes, imeInTheHistory, subtypeInTheHistory);
if (!TextUtils.isEmpty(subtypeHashCode)) {
if (DEBUG) {
Slog.d(TAG, "Enabled subtype found in the history:" + subtypeHashCode);
@@ -2532,14 +2536,36 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
return null;
}
- private String getEnabledSubtypeForInputMethodAndSubtypeLocked(List<Pair<String,
+ private String getEnabledSubtypeHashCodeForInputMethodAndSubtypeLocked(List<Pair<String,
ArrayList<String>>> enabledImes, String imeId, String subtypeHashCode) {
for (Pair<String, ArrayList<String>> enabledIme: enabledImes) {
if (enabledIme.first.equals(imeId)) {
- for (String s: enabledIme.second) {
- if (s.equals(subtypeHashCode)) {
- // If both imeId and subtypeId are enabled, return subtypeId.
- return s;
+ final ArrayList<String> enabledSubtypes = enabledIme.second;
+ if (enabledSubtypes.size() == 0) {
+ // If there are no enabled subtypes, applicable subtypes are enabled
+ // implicitly.
+ InputMethodInfo ime = mMethodMap.get(imeId);
+ // If IME is enabled and no subtypes are enabled, applicable subtypes
+ // are enabled implicitly, so needs to treat them to be enabled.
+ if (ime != null && ime.getSubtypes().size() > 0) {
+ List<InputMethodSubtype> implicitlySelectedSubtypes =
+ getApplicableSubtypesLocked(mRes, ime.getSubtypes());
+ if (implicitlySelectedSubtypes != null) {
+ final int N = implicitlySelectedSubtypes.size();
+ for (int i = 0; i < N; ++i) {
+ final InputMethodSubtype st = implicitlySelectedSubtypes.get(i);
+ if (String.valueOf(st.hashCode()).equals(subtypeHashCode)) {
+ return subtypeHashCode;
+ }
+ }
+ }
+ }
+ } else {
+ for (String s: enabledSubtypes) {
+ if (s.equals(subtypeHashCode)) {
+ // If both imeId and subtypeId are enabled, return subtypeId.
+ return s;
+ }
}
}
// If imeId was enabled but subtypeId was disabled.
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 95534e356110..6f4b4c5be403 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -481,14 +481,11 @@ class ServerThread extends Thread {
// we are in safe mode.
final boolean safeMode = wm.detectSafeMode();
if (safeMode) {
- try {
- ActivityManagerNative.getDefault().enterSafeMode();
- // Post the safe mode state in the Zygote class
- Zygote.systemInSafeMode = true;
- // Disable the JIT for the system_server process
- VMRuntime.getRuntime().disableJitCompilation();
- } catch (RemoteException e) {
- }
+ ActivityManagerService.self().enterSafeMode();
+ // Post the safe mode state in the Zygote class
+ Zygote.systemInSafeMode = true;
+ // Disable the JIT for the system_server process
+ VMRuntime.getRuntime().disableJitCompilation();
} else {
// Enable the JIT for the system_server process
VMRuntime.getRuntime().startJitCompilation();
@@ -506,6 +503,10 @@ class ServerThread extends Thread {
wm.systemReady();
+ if (safeMode) {
+ ActivityManagerService.self().showSafeModeOverlay();
+ }
+
// Update the configuration for this context by hand, because we're going
// to start using it before the config change done in wm.systemReady() will
// propagate to it.
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java
index 8d9cb31c013b..bdc779c3e11e 100644
--- a/services/java/com/android/server/WindowManagerService.java
+++ b/services/java/com/android/server/WindowManagerService.java
@@ -212,6 +212,10 @@ public class WindowManagerService extends IWindowManager.Stub
// Maximum number of milliseconds to wait for input event injection.
// FIXME is this value reasonable?
private static final int INJECTION_TIMEOUT_MILLIS = 30 * 1000;
+
+ // Maximum number of milliseconds to wait for input devices to be enumerated before
+ // proceding with safe mode detection.
+ private static final int INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS = 1000;
// Default input dispatching timeout in nanoseconds.
private static final long DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS = 5000 * 1000000L;
@@ -5812,6 +5816,11 @@ public class WindowManagerService extends IWindowManager.Stub
// Temporary input application object to provide to the input dispatcher.
private InputApplication mTempInputApplication = new InputApplication();
+ // Set to true when the first input device configuration change notification
+ // is received to indicate that the input devices are ready.
+ private final Object mInputDevicesReadyMonitor = new Object();
+ private boolean mInputDevicesReady;
+
/* Notifies the window manager about a broken input channel.
*
* Called by the InputManager.
@@ -6007,7 +6016,32 @@ public class WindowManagerService extends IWindowManager.Stub
// Also avoids keeping InputChannel objects referenced unnecessarily.
mTempInputWindows.clear();
}
-
+
+ /* Notifies that the input device configuration has changed. */
+ public void notifyConfigurationChanged() {
+ sendNewConfiguration();
+
+ synchronized (mInputDevicesReadyMonitor) {
+ if (!mInputDevicesReady) {
+ mInputDevicesReady = true;
+ mInputDevicesReadyMonitor.notifyAll();
+ }
+ }
+ }
+
+ /* Waits until the built-in input devices have been configured. */
+ public boolean waitForInputDevicesReady(long timeoutMillis) {
+ synchronized (mInputDevicesReadyMonitor) {
+ if (!mInputDevicesReady) {
+ try {
+ mInputDevicesReadyMonitor.wait(timeoutMillis);
+ } catch (InterruptedException ex) {
+ }
+ }
+ return mInputDevicesReady;
+ }
+ }
+
/* Notifies that the lid switch changed state. */
public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen) {
mPolicy.notifyLidSwitchChanged(whenNanos, lidOpen);
@@ -6329,6 +6363,13 @@ public class WindowManagerService extends IWindowManager.Stub
}
public boolean detectSafeMode() {
+ if (!mInputMonitor.waitForInputDevicesReady(
+ INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS)) {
+ Slog.w(TAG, "Devices still not ready after waiting "
+ + INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS
+ + " milliseconds before attempting to detect safe mode.");
+ }
+
mSafeMode = mPolicy.detectSafeMode();
return mSafeMode;
}
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 17ef88d96f44..dbf9a96a8739 100755
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -6075,23 +6075,25 @@ public final class ActivityManagerService extends ActivityManagerNative
AppGlobals.getPackageManager().enterSafeMode();
} catch (RemoteException e) {
}
-
- View v = LayoutInflater.from(mContext).inflate(
- com.android.internal.R.layout.safe_mode, null);
- WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
- lp.type = WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
- lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
- lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
- lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
- lp.format = v.getBackground().getOpacity();
- lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
- | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
- ((WindowManager)mContext.getSystemService(
- Context.WINDOW_SERVICE)).addView(v, lp);
}
}
}
+ public final void showSafeModeOverlay() {
+ View v = LayoutInflater.from(mContext).inflate(
+ com.android.internal.R.layout.safe_mode, null);
+ WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
+ lp.type = WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
+ lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
+ lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
+ lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
+ lp.format = v.getBackground().getOpacity();
+ lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+ | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
+ ((WindowManager)mContext.getSystemService(
+ Context.WINDOW_SERVICE)).addView(v, lp);
+ }
+
public void noteWakeupAlarm(IIntentSender sender) {
if (!(sender instanceof PendingIntentRecord)) {
return;
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java b/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java
index 9ccb3eed7892..a3466e27e597 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java
@@ -75,6 +75,7 @@ public class TestShellActivity extends Activity implements LayoutTestController
public void handleMessage(Message msg) {
if (msg.what == MSG_TIMEOUT) {
mTimedOut = true;
+ mWebView.stopLoading();
if (mCallback != null)
mCallback.timedOut(mWebView.getUrl());
if (!mRequestedWebKitData) {
diff --git a/tools/layoutlib/bridge/src/android/graphics/BitmapFactory.java b/tools/layoutlib/bridge/src/android/graphics/BitmapFactory.java
index 7020d9cbfcea..db3cf44d89c8 100644
--- a/tools/layoutlib/bridge/src/android/graphics/BitmapFactory.java
+++ b/tools/layoutlib/bridge/src/android/graphics/BitmapFactory.java
@@ -353,7 +353,7 @@ public class BitmapFactory {
If it happened on close, bm is still valid.
*/
Bridge.getLog().error(LayoutLog.TAG_RESOURCES_READ,
- String.format("Error decoding bitmap of id 0x%x", id), e);
+ String.format("Error decoding bitmap of id 0x%x", id), e, null /*data*/);
} finally {
try {
if (is != null) is.close();
@@ -454,7 +454,7 @@ public class BitmapFactory {
if (is instanceof AssetManager.AssetInputStream) {
Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED,
"Bitmap.decodeStream: " +
- "InputStream is unsupported (AssetManager.AssetInputStream)");
+ "InputStream is unsupported (AssetManager.AssetInputStream)", null /*data*/);
return null;
} else {
// pass some temp storage down to the native code. 1024 is made up,
diff --git a/tools/layoutlib/bridge/src/android/graphics/BitmapShader_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/BitmapShader_Delegate.java
index 03d65b2ed969..73c5a1aceab4 100644
--- a/tools/layoutlib/bridge/src/android/graphics/BitmapShader_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/BitmapShader_Delegate.java
@@ -114,7 +114,7 @@ public class BitmapShader_Delegate extends Shader_Delegate {
canvasMatrix = xform.createInverse();
} catch (java.awt.geom.NoninvertibleTransformException e) {
Bridge.getLog().fidelityWarning(LayoutLog.TAG_MATRIX_INVERSE,
- "Unable to inverse matrix in BitmapShader", e);
+ "Unable to inverse matrix in BitmapShader", e, null /*data*/);
canvasMatrix = new java.awt.geom.AffineTransform();
}
@@ -123,7 +123,7 @@ public class BitmapShader_Delegate extends Shader_Delegate {
localMatrix = localMatrix.createInverse();
} catch (java.awt.geom.NoninvertibleTransformException e) {
Bridge.getLog().fidelityWarning(LayoutLog.TAG_MATRIX_INVERSE,
- "Unable to inverse matrix in BitmapShader", e);
+ "Unable to inverse matrix in BitmapShader", e, null /*data*/);
localMatrix = new java.awt.geom.AffineTransform();
}
diff --git a/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java
index 18bf4b58ff08..108d1838db7b 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java
@@ -250,7 +250,7 @@ public final class Bitmap_Delegate {
/*package*/ static boolean nativeCompress(int nativeBitmap, int format, int quality,
OutputStream stream, byte[] tempStorage) {
Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED,
- "Bitmap.compress() is not supported");
+ "Bitmap.compress() is not supported", null /*data*/);
return true;
}
@@ -386,7 +386,8 @@ public final class Bitmap_Delegate {
// This is only called by Bitmap.CREATOR (Parcelable.Creator<Bitmap>), which is only
// used during aidl call so really this should not be called.
Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED,
- "AIDL is not suppored, and therefore Bitmaps cannot be created from parcels.");
+ "AIDL is not suppored, and therefore Bitmaps cannot be created from parcels.",
+ null /*data*/);
return null;
}
@@ -395,7 +396,8 @@ public final class Bitmap_Delegate {
// This is only called when sending a bitmap through aidl, so really this should not
// be called.
Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED,
- "AIDL is not suppored, and therefore Bitmaps cannot be written to parcels.");
+ "AIDL is not suppored, and therefore Bitmaps cannot be written to parcels.",
+ null /*data*/);
return false;
}
@@ -412,7 +414,7 @@ public final class Bitmap_Delegate {
if (paint != null && paint.getMaskFilter() != null) {
Bridge.getLog().fidelityWarning(LayoutLog.TAG_MASKFILTER,
"MaskFilter not supported in Bitmap.extractAlpha",
- null);
+ null, null /*data*/);
}
int alpha = paint != null ? paint.getAlpha() : 0xFF;
diff --git a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
index 8bfaf4041200..5a6902c074dc 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
@@ -425,7 +425,7 @@ public final class Canvas_Delegate {
assert false;
Bridge.getLog().fidelityWarning(LayoutLog.TAG_MATRIX_AFFINE,
"android.graphics.Canvas#setMatrix(android.graphics.Matrix) only " +
- "supports affine transformations.", null);
+ "supports affine transformations.", null, null /*data*/);
}
}
@@ -494,7 +494,7 @@ public final class Canvas_Delegate {
if (filterDelegate.isSupported() == false) {
Bridge.getLog().fidelityWarning(LayoutLog.TAG_DRAWFILTER,
- filterDelegate.getSupportMessage(), null);
+ filterDelegate.getSupportMessage(), null, null /*data*/);
}
}
diff --git a/tools/layoutlib/bridge/src/android/graphics/LinearGradient_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/LinearGradient_Delegate.java
index aab310aa626e..9525dcf8e049 100644
--- a/tools/layoutlib/bridge/src/android/graphics/LinearGradient_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/LinearGradient_Delegate.java
@@ -137,7 +137,7 @@ public final class LinearGradient_Delegate extends Gradient_Delegate {
canvasMatrix = xform.createInverse();
} catch (java.awt.geom.NoninvertibleTransformException e) {
Bridge.getLog().fidelityWarning(LayoutLog.TAG_MATRIX_INVERSE,
- "Unable to inverse matrix in LinearGradient", e);
+ "Unable to inverse matrix in LinearGradient", e, null /*data*/);
canvasMatrix = new java.awt.geom.AffineTransform();
}
@@ -146,7 +146,7 @@ public final class LinearGradient_Delegate extends Gradient_Delegate {
localMatrix = localMatrix.createInverse();
} catch (java.awt.geom.NoninvertibleTransformException e) {
Bridge.getLog().fidelityWarning(LayoutLog.TAG_MATRIX_INVERSE,
- "Unable to inverse matrix in LinearGradient", e);
+ "Unable to inverse matrix in LinearGradient", e, null /*data*/);
localMatrix = new java.awt.geom.AffineTransform();
}
diff --git a/tools/layoutlib/bridge/src/android/graphics/Matrix_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Matrix_Delegate.java
index 0c934fccaa4d..2d77d40f6f54 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Matrix_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Matrix_Delegate.java
@@ -615,7 +615,7 @@ public final class Matrix_Delegate {
// FIXME
Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
"Matrix.setPolyToPoly is not supported.",
- null);
+ null, null /*data*/);
return false;
}
diff --git a/tools/layoutlib/bridge/src/android/graphics/NinePatch_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/NinePatch_Delegate.java
index 049ac454c165..7a6da95dbb89 100644
--- a/tools/layoutlib/bridge/src/android/graphics/NinePatch_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/NinePatch_Delegate.java
@@ -74,7 +74,7 @@ public final class NinePatch_Delegate {
oos = new ObjectOutputStream(baos);
oos.writeObject(chunk);
} catch (IOException e) {
- Bridge.getLog().error(null, "Failed to serialize NinePatchChunk.", e);
+ Bridge.getLog().error(null, "Failed to serialize NinePatchChunk.", e, null /*data*/);
return null;
} finally {
if (oos != null) {
@@ -198,11 +198,11 @@ public final class NinePatch_Delegate {
}
} catch (IOException e) {
Bridge.getLog().error(LayoutLog.TAG_BROKEN,
- "Failed to deserialize NinePatchChunk content.", e);
+ "Failed to deserialize NinePatchChunk content.", e, null /*data*/);
return null;
} catch (ClassNotFoundException e) {
Bridge.getLog().error(LayoutLog.TAG_BROKEN,
- "Failed to deserialize NinePatchChunk class.", e);
+ "Failed to deserialize NinePatchChunk class.", e, null /*data*/);
return null;
} finally {
if (ois != null) {
diff --git a/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java
index 67afecae3493..87164fb42e0b 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java
@@ -182,7 +182,7 @@ public class Paint_Delegate {
} else {
Bridge.getLog().fidelityWarning(LayoutLog.TAG_PATHEFFECT,
effectDelegate.getSupportMessage(),
- null);
+ null, null /*data*/);
}
}
@@ -377,7 +377,7 @@ public class Paint_Delegate {
int color) {
// FIXME
Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
- "Paint.setShadowLayer is not supported.", null);
+ "Paint.setShadowLayer is not supported.", null, null /*data*/);
}
/*package*/ static float getTextSize(Paint thisPaint) {
@@ -694,7 +694,7 @@ public class Paint_Delegate {
ColorFilter_Delegate filterDelegate = delegate.getColorFilter();
if (filterDelegate != null && filterDelegate.isSupported() == false) {
Bridge.getLog().fidelityWarning(LayoutLog.TAG_COLORFILTER,
- filterDelegate.getSupportMessage(), null);
+ filterDelegate.getSupportMessage(), null, null /*data*/);
}
return filter;
@@ -733,7 +733,7 @@ public class Paint_Delegate {
MaskFilter_Delegate filterDelegate = delegate.getMaskFilter();
if (filterDelegate != null && filterDelegate.isSupported() == false) {
Bridge.getLog().fidelityWarning(LayoutLog.TAG_MASKFILTER,
- filterDelegate.getSupportMessage(), null);
+ filterDelegate.getSupportMessage(), null, null /*data*/);
}
return maskfilter;
@@ -764,7 +764,7 @@ public class Paint_Delegate {
Rasterizer_Delegate rasterizerDelegate = delegate.getRasterizer();
if (rasterizerDelegate != null && rasterizerDelegate.isSupported() == false) {
Bridge.getLog().fidelityWarning(LayoutLog.TAG_RASTERIZER,
- rasterizerDelegate.getSupportMessage(), null);
+ rasterizerDelegate.getSupportMessage(), null, null /*data*/);
}
return rasterizer;
diff --git a/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java
index 62ea62230061..a4e43c111879 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java
@@ -698,7 +698,7 @@ public final class Path_Delegate {
assert false;
Bridge.getLog().fidelityWarning(LayoutLog.TAG_MATRIX_AFFINE,
"android.graphics.Path#transform() only " +
- "supports affine transformations.", null);
+ "supports affine transformations.", null, null /*data*/);
}
GeneralPath newPath = new GeneralPath();
diff --git a/tools/layoutlib/bridge/src/android/graphics/PorterDuffXfermode_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/PorterDuffXfermode_Delegate.java
index 314dcff212a9..147e1d0e7607 100644
--- a/tools/layoutlib/bridge/src/android/graphics/PorterDuffXfermode_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/PorterDuffXfermode_Delegate.java
@@ -74,7 +74,7 @@ public class PorterDuffXfermode_Delegate extends Xfermode_Delegate {
}
Bridge.getLog().error(LayoutLog.TAG_BROKEN,
- String.format("Unknown PorterDuff.Mode: %d", mode));
+ String.format("Unknown PorterDuff.Mode: %d", mode), null /*data*/);
assert false;
return PorterDuff.Mode.SRC_OVER;
}
@@ -118,7 +118,7 @@ public class PorterDuffXfermode_Delegate extends Xfermode_Delegate {
Bridge.getLog().fidelityWarning(LayoutLog.TAG_BROKEN,
String.format("Unsupported PorterDuff Mode: %s", mode.name()),
- null);
+ null, null /*data*/);
return AlphaComposite.getInstance(AlphaComposite.SRC_OVER, falpha);
}
diff --git a/tools/layoutlib/bridge/src/android/graphics/RadialGradient_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/RadialGradient_Delegate.java
index 2c26175d75d9..ffdf5ddb02c9 100644
--- a/tools/layoutlib/bridge/src/android/graphics/RadialGradient_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/RadialGradient_Delegate.java
@@ -126,7 +126,7 @@ public class RadialGradient_Delegate extends Gradient_Delegate {
canvasMatrix = xform.createInverse();
} catch (java.awt.geom.NoninvertibleTransformException e) {
Bridge.getLog().fidelityWarning(LayoutLog.TAG_MATRIX_INVERSE,
- "Unable to inverse matrix in RadialGradient", e);
+ "Unable to inverse matrix in RadialGradient", e, null /*data*/);
canvasMatrix = new java.awt.geom.AffineTransform();
}
@@ -135,7 +135,7 @@ public class RadialGradient_Delegate extends Gradient_Delegate {
localMatrix = localMatrix.createInverse();
} catch (java.awt.geom.NoninvertibleTransformException e) {
Bridge.getLog().fidelityWarning(LayoutLog.TAG_MATRIX_INVERSE,
- "Unable to inverse matrix in RadialGradient", e);
+ "Unable to inverse matrix in RadialGradient", e, null /*data*/);
localMatrix = new java.awt.geom.AffineTransform();
}
diff --git a/tools/layoutlib/bridge/src/android/graphics/Region_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Region_Delegate.java
index f86c56cc2a2c..9b6fb82a6329 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Region_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Region_Delegate.java
@@ -417,7 +417,8 @@ public class Region_Delegate {
// This is only called by Region.CREATOR (Parcelable.Creator<Region>), which is only
// used during aidl call so really this should not be called.
Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED,
- "AIDL is not suppored, and therefore Regions cannot be created from parcels.");
+ "AIDL is not suppored, and therefore Regions cannot be created from parcels.",
+ null /*data*/);
return 0;
}
@@ -426,7 +427,8 @@ public class Region_Delegate {
// This is only called when sending a region through aidl, so really this should not
// be called.
Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED,
- "AIDL is not suppored, and therefore Regions cannot be written to parcels.");
+ "AIDL is not suppored, and therefore Regions cannot be written to parcels.",
+ null /*data*/);
return false;
}
diff --git a/tools/layoutlib/bridge/src/android/graphics/SweepGradient_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/SweepGradient_Delegate.java
index e812f7f0031e..048990a21a75 100644
--- a/tools/layoutlib/bridge/src/android/graphics/SweepGradient_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/SweepGradient_Delegate.java
@@ -118,7 +118,7 @@ public class SweepGradient_Delegate extends Gradient_Delegate {
canvasMatrix = xform.createInverse();
} catch (java.awt.geom.NoninvertibleTransformException e) {
Bridge.getLog().fidelityWarning(LayoutLog.TAG_MATRIX_INVERSE,
- "Unable to inverse matrix in SweepGradient", e);
+ "Unable to inverse matrix in SweepGradient", e, null /*data*/);
canvasMatrix = new java.awt.geom.AffineTransform();
}
@@ -127,7 +127,7 @@ public class SweepGradient_Delegate extends Gradient_Delegate {
localMatrix = localMatrix.createInverse();
} catch (java.awt.geom.NoninvertibleTransformException e) {
Bridge.getLog().fidelityWarning(LayoutLog.TAG_MATRIX_INVERSE,
- "Unable to inverse matrix in SweepGradient", e);
+ "Unable to inverse matrix in SweepGradient", e, null /*data*/);
localMatrix = new java.awt.geom.AffineTransform();
}
diff --git a/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java
index 44275d6ab928..00a2a57951dd 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java
@@ -127,13 +127,13 @@ public final class Typeface_Delegate {
/*package*/ static synchronized int nativeCreateFromAsset(AssetManager mgr, String path) {
Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
- "Typeface.createFromAsset() is not supported.", null);
+ "Typeface.createFromAsset() is not supported.", null /*throwable*/, null /*data*/);
return 0;
}
/*package*/ static synchronized int nativeCreateFromFile(String path) {
Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
- "Typeface.createFromFile() is not supported.", null);
+ "Typeface.createFromFile() is not supported.", null /*throwable*/, null /*data*/);
return 0;
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
index 6e9f4d5ab76e..37576b4ec9c0 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
@@ -137,17 +137,17 @@ public final class Bridge extends com.android.ide.common.rendering.api.Bridge {
*/
private final static LayoutLog sDefaultLog = new LayoutLog() {
@Override
- public void error(String tag, String message) {
+ public void error(String tag, String message, Object data) {
System.err.println(message);
}
@Override
- public void error(String tag, String message, Throwable throwable) {
+ public void error(String tag, String message, Throwable throwable, Object data) {
System.err.println(message);
}
@Override
- public void warning(String tag, String message) {
+ public void warning(String tag, String message, Object data) {
System.out.println(message);
}
};
@@ -207,7 +207,7 @@ public final class Bridge extends com.android.ide.common.rendering.api.Bridge {
@Override
public void onInvokeV(String signature, boolean isNative, Object caller) {
sDefaultLog.error(null, "Missing Stub: " + signature +
- (isNative ? " (native)" : ""));
+ (isNative ? " (native)" : ""), null /*data*/);
if (debug.equalsIgnoreCase("throw")) {
// Throwing this exception doesn't seem that useful. It breaks
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
index dc027b7df0f6..82e217a677ab 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
@@ -254,6 +254,11 @@ public final class BridgeContext extends Activity {
return null;
}
+ // needed by SearchView
+ if (INPUT_METHOD_SERVICE.equals(service)) {
+ return null;
+ }
+
throw new UnsupportedOperationException("Unsupported Service: " + service);
}
@@ -338,7 +343,7 @@ public final class BridgeContext extends Activity {
} else if (set != null) { // null parser is ok
// really this should not be happening since its instantiated in Bridge
Bridge.getLog().error(LayoutLog.TAG_BROKEN,
- "Parser is not a BridgeXmlBlockParser!");
+ "Parser is not a BridgeXmlBlockParser!", null /*data*/);
return null;
}
@@ -386,7 +391,8 @@ public final class BridgeContext extends Activity {
} else {
Bridge.getLog().error(null,
String.format(
- "Failed to find style '%s' in current theme", defStyleName));
+ "Failed to find style '%s' in current theme", defStyleName),
+ null /*data*/);
}
}
}
@@ -443,7 +449,7 @@ public final class BridgeContext extends Activity {
} else {
// there is a value in the XML, but we need to resolve it in case it's
// referencing another resource or a theme value.
- ta.bridgeSetValue(index, name, resolveValue(null, name, value));
+ ta.bridgeSetValue(index, name, resolveValue(null, name, value, isPlatformFile));
}
}
}
@@ -506,21 +512,24 @@ public final class BridgeContext extends Activity {
* @param type the type of the resource
* @param name the name of the attribute containing this value.
* @param value the resource value, or reference to resolve
+ * @param isFrameworkValue whether the value is a framework value.
+ *
* @return the resolved resource value or <code>null</code> if it failed to resolve it.
*/
- private ResourceValue resolveValue(String type, String name, String value) {
+ private ResourceValue resolveValue(String type, String name, String value,
+ boolean isFrameworkValue) {
if (value == null) {
return null;
}
// get the ResourceValue referenced by this value
- ResourceValue resValue = findResValue(value, false /*forceFrameworkOnly*/);
+ ResourceValue resValue = findResValue(value, isFrameworkValue);
// if resValue is null, but value is not null, this means it was not a reference.
// we return the name/value wrapper in a ResourceValue. the isFramework flag doesn't
// matter.
if (resValue == null) {
- return new ResourceValue(type, name, value, false /*isFramework*/);
+ return new ResourceValue(type, name, value, isFrameworkValue);
}
// we resolved a first reference, but we need to make sure this isn't a reference also.
@@ -701,6 +710,15 @@ public final class BridgeContext extends Activity {
if (item != null) {
return item;
}
+
+ // if it was not found and the type is an id, it is possible that the ID was
+ // generated dynamically when compiling the framework resources.
+ // Look for it in the R map.
+ if (BridgeConstants.RES_ID.equals(resType)) {
+ if (Bridge.getResourceValue(resType, resName) != null) {
+ return new ResourceValue(resType, resName, true);
+ }
+ }
}
// didn't find the resource anywhere.
@@ -709,7 +727,8 @@ public final class BridgeContext extends Activity {
if ("+id".equals(resType) == false && "+android:id".equals(resType) == false) { //$NON-NLS-1$ //$NON-NLS-2$
Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_RESOLVE,
"Couldn't resolve resource @" +
- (frameworkOnly ? "android:" : "") + resType + "/" + resName);
+ (frameworkOnly ? "android:" : "") + resType + "/" + resName,
+ new ResourceValue(resType, resName, frameworkOnly));
}
return null;
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeInflater.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeInflater.java
index 61ac81bee4a6..e95d295bb608 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeInflater.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeInflater.java
@@ -180,7 +180,7 @@ public final class BridgeInflater extends LayoutInflater {
return inflate(bridgeParser, root);
} catch (Exception e) {
Bridge.getLog().error(LayoutLog.TAG_RESOURCES_READ,
- "Failed to parse file " + f.getAbsolutePath(), e);
+ "Failed to parse file " + f.getAbsolutePath(), e, null /*data*/);
return null;
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeResources.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeResources.java
index 8446a990a9c3..23d81a2b7ba7 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeResources.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeResources.java
@@ -143,7 +143,8 @@ public final class BridgeResources extends Resources {
try {
return ResourceHelper.getColor(value.getValue());
} catch (NumberFormatException e) {
- Bridge.getLog().error(LayoutLog.TAG_RESOURCES_FORMAT, e.getMessage(), e);
+ Bridge.getLog().error(LayoutLog.TAG_RESOURCES_FORMAT, e.getMessage(), e,
+ null /*data*/);
return 0;
}
}
@@ -176,13 +177,13 @@ public final class BridgeResources extends Resources {
new BridgeXmlBlockParser(parser, mContext, resValue.isFramework()));
} catch (XmlPullParserException e) {
Bridge.getLog().error(LayoutLog.TAG_BROKEN,
- "Failed to configure parser for " + value, e);
+ "Failed to configure parser for " + value, e, null /*data*/);
// we'll return null below.
} catch (Exception e) {
// this is an error and not warning since the file existence is checked before
// attempting to parse it.
Bridge.getLog().error(LayoutLog.TAG_RESOURCES_READ,
- "Failed to parse file " + value, e);
+ "Failed to parse file " + value, e, null /*data*/);
return null;
}
@@ -193,7 +194,8 @@ public final class BridgeResources extends Resources {
return ColorStateList.valueOf(color);
} catch (NumberFormatException e) {
Bridge.getLog().error(LayoutLog.TAG_RESOURCES_FORMAT,
- "Failed to convert " + value + " into a ColorStateList", e);
+ "Failed to convert " + value + " into a ColorStateList", e,
+ null /*data*/);
return null;
}
}
@@ -253,7 +255,7 @@ public final class BridgeResources extends Resources {
}
} catch (XmlPullParserException e) {
Bridge.getLog().error(LayoutLog.TAG_BROKEN,
- "Failed to configure parser for " + value.getValue(), e);
+ "Failed to configure parser for " + value.getValue(), e, null /*data*/);
// we'll return null below.
} catch (FileNotFoundException e) {
// this shouldn't happen since we check above.
@@ -288,7 +290,7 @@ public final class BridgeResources extends Resources {
}
} catch (XmlPullParserException e) {
Bridge.getLog().error(LayoutLog.TAG_BROKEN,
- "Failed to configure parser for " + value.getValue(), e);
+ "Failed to configure parser for " + value.getValue(), e, null /*data*/);
// we'll return null below.
} catch (FileNotFoundException e) {
// this shouldn't happen since we check above.
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeTypedArray.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeTypedArray.java
index 42f05e381594..84bb4d1dd304 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeTypedArray.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeTypedArray.java
@@ -207,10 +207,10 @@ public final class BridgeTypedArray extends TypedArray {
if (i != null) {
result |= i.intValue();
} else {
- Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_RESOLVE,
+ Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_FORMAT,
String.format(
- "Unknown constant \"%s\" in attribute \"%2$s\"",
- keyword, mNames[index]));
+ "\"%s\" in attribute \"%2$s\" is not a valid value",
+ keyword, mNames[index]), null /*data*/);
}
}
return result;
@@ -238,10 +238,10 @@ public final class BridgeTypedArray extends TypedArray {
try {
return Float.parseFloat(s);
} catch (NumberFormatException e) {
- Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_RESOLVE,
+ Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_FORMAT,
String.format(
- "Unable to convert \"%s\" into a float in attribute \"%2$s\"",
- s, mNames[index]));
+ "\"%s\" in attribute \"%2$s\" cannot be converted to float.",
+ s, mNames[index]), null /*data*/);
// we'll return the default value below.
}
@@ -271,7 +271,7 @@ public final class BridgeTypedArray extends TypedArray {
try {
return ResourceHelper.getColor(s);
} catch (NumberFormatException e) {
- Bridge.getLog().error(LayoutLog.TAG_RESOURCES_FORMAT, e.getMessage(), e);
+ Bridge.getLog().error(LayoutLog.TAG_RESOURCES_FORMAT, e.getMessage(), e, null /*data*/);
// we'll return the default value below.
}
@@ -315,13 +315,13 @@ public final class BridgeTypedArray extends TypedArray {
return colorStateList;
} catch (XmlPullParserException e) {
Bridge.getLog().error(LayoutLog.TAG_BROKEN,
- "Failed to configure parser for " + value, e);
+ "Failed to configure parser for " + value, e, null /*data*/);
return null;
} catch (Exception e) {
// this is an error and not warning since the file existence is checked before
// attempting to parse it.
Bridge.getLog().error(LayoutLog.TAG_RESOURCES_READ,
- "Failed to parse file " + value, e);
+ "Failed to parse file " + value, e, null /*data*/);
return null;
}
@@ -331,7 +331,7 @@ public final class BridgeTypedArray extends TypedArray {
int color = ResourceHelper.getColor(value);
return ColorStateList.valueOf(color);
} catch (NumberFormatException e) {
- Bridge.getLog().error(LayoutLog.TAG_RESOURCES_FORMAT, e.getMessage(), e);
+ Bridge.getLog().error(LayoutLog.TAG_RESOURCES_FORMAT, e.getMessage(), e, null /*data*/);
}
assert false;
@@ -360,10 +360,10 @@ public final class BridgeTypedArray extends TypedArray {
try {
return Integer.parseInt(s);
} catch (NumberFormatException e) {
- Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_RESOLVE,
+ Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_FORMAT,
String.format(
- "Unable to convert \"%s\" into a integer in attribute \"%2$s\"",
- s, mNames[index]));
+ "\"%s\" in attribute \"%2$s\" cannont be converted to an integer.",
+ s, mNames[index]), null /*data*/);
// The default value is returned below.
}
@@ -410,10 +410,10 @@ public final class BridgeTypedArray extends TypedArray {
}
// looks like we were unable to resolve the dimension value
- Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_RESOLVE,
+ Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_FORMAT,
String.format(
- "Unable to resolve dimension value \"%1$s\" in attribute \"%2$s\"",
- s, mNames[index]));
+ "\"%1$s\" in attribute \"%2$s\" is not a valid format.",
+ s, mNames[index]), null /*data*/);
assert false;
@@ -542,10 +542,10 @@ public final class BridgeTypedArray extends TypedArray {
}
// looks like we were unable to resolve the fraction value
- Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_RESOLVE,
+ Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_FORMAT,
String.format(
- "Unable to resolve fraction value \"%1$s\" in attribute \"%2$s\"",
- value, mNames[index]));
+ "\"%1$s\" in attribute \"%2$s\" cannont be converted to a fraction.",
+ value, mNames[index]), null /*data*/);
assert false;
@@ -656,7 +656,8 @@ public final class BridgeTypedArray extends TypedArray {
Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_RESOLVE,
String.format(
- "Unable to resolve id \"%1$s\" for attribute \"%2$s\"", value, mNames[index]));
+ "Unable to resolve id \"%1$s\" for attribute \"%2$s\"", value, mNames[index]),
+ resValue);
assert false;
@@ -685,21 +686,7 @@ public final class BridgeTypedArray extends TypedArray {
return null;
}
- Drawable d = ResourceHelper.getDrawable(value, mContext, mResourceData[index].isFramework());
-
- if (d != null) {
- return d;
- }
-
- // looks like we were unable to resolve the drawable
- Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_RESOLVE,
- String.format(
- "Unable to resolve drawable \"%1$s\" in attribute \"%2$s\"", stringValue,
- mNames[index]));
-
- assert false;
-
- return null;
+ return ResourceHelper.getDrawable(value, mContext, mResourceData[index].isFramework());
}
@@ -724,10 +711,10 @@ public final class BridgeTypedArray extends TypedArray {
return new CharSequence[] { value };
}
- Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_RESOLVE,
+ Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_FORMAT,
String.format(
String.format("Unknown value for getTextArray(%d) => %s", //DEBUG
- index, mResourceData[index].getName())));
+ index, mResourceData[index].getName())), null /*data*/);
return null;
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/GcSnapshot.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/GcSnapshot.java
index b3f1fff2c3c7..21d6b1a67505 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/GcSnapshot.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/GcSnapshot.java
@@ -393,27 +393,26 @@ public class GcSnapshot {
* @param bitmap the bitmap to link to.
*/
public void setBitmap(Bitmap_Delegate bitmap) {
- assert mLayers.size() == 0;
-
// create a new Layer for the bitmap. This will be the base layer.
Graphics2D graphics2D = bitmap.getImage().createGraphics();
Layer baseLayer = new Layer(graphics2D, bitmap);
- // add it to the list.
- mLayers.add(baseLayer);
+ // Set the current transform and clip which can either come from mTransform/mClip if they
+ // were set when there was no bitmap/layers or from the current base layers if there is
+ // one already.
- // if transform and clip where modified before, get the information and give it to the
- // layer.
+ graphics2D.setTransform(getTransform());
+ // reset mTransform in case there was one.
+ mTransform = null;
- if (mTransform != null) {
- graphics2D.setTransform(mTransform);
- mTransform = null;
- }
+ baseLayer.setClip(getClip());
+ // reset mClip in case there was one.
+ mClip = null;
+
+ // replace whatever current layers we have with this.
+ mLayers.clear();
+ mLayers.add(baseLayer);
- if (mClip != null) {
- baseLayer.setClip(mClip);
- mClip = null;
- }
}
public void translate(float dx, float dy) {
@@ -731,7 +730,7 @@ public class GcSnapshot {
} else {
Bridge.getLog().fidelityWarning(LayoutLog.TAG_SHADER,
shaderDelegate.getSupportMessage(),
- null);
+ null /*throwable*/, null /*data*/);
}
}
@@ -765,7 +764,7 @@ public class GcSnapshot {
} else {
Bridge.getLog().fidelityWarning(LayoutLog.TAG_XFERMODE,
xfermodeDelegate.getSupportMessage(),
- null);
+ null /*throwable*/, null /*data*/);
}
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
index 566d4d4a87f8..2439791f0097 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
@@ -1046,7 +1046,8 @@ public class RenderSessionImpl {
assert false;
mParams.getLog().error(LayoutLog.TAG_RESOURCES_RESOLVE,
- String.format("Unable to resolve parent style name: %s", parentName));
+ String.format("Unable to resolve parent style name: %s", parentName),
+ null /*data*/);
return null;
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java
index 4e331d1f9368..475b4be25314 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java
@@ -166,7 +166,7 @@ public final class ResourceHelper {
} catch (IOException e) {
// failed to read the file, we'll return null below.
Bridge.getLog().error(LayoutLog.TAG_RESOURCES_READ,
- "Failed lot load " + file.getAbsolutePath(), e);
+ "Failed lot load " + file.getAbsolutePath(), e, null /*data*/);
}
}
@@ -197,11 +197,12 @@ public final class ResourceHelper {
} catch (Exception e) {
// this is an error and not warning since the file existence is checked before
// attempting to parse it.
- Bridge.getLog().error(null, "Failed to parse file " + value, e);
+ Bridge.getLog().error(null, "Failed to parse file " + value, e, null /*data*/);
}
} else {
Bridge.getLog().error(LayoutLog.TAG_BROKEN,
- String.format("File %s does not exist (or is not a file)", stringValue));
+ String.format("File %s does not exist (or is not a file)", stringValue),
+ null /*data*/);
}
return null;
@@ -228,7 +229,7 @@ public final class ResourceHelper {
} catch (IOException e) {
// we'll return null below
Bridge.getLog().error(LayoutLog.TAG_RESOURCES_READ,
- "Failed lot load " + bmpFile.getAbsolutePath(), e);
+ "Failed lot load " + bmpFile.getAbsolutePath(), e, null /*data*/);
}
} else {
// attempt to get a color from the value
@@ -238,7 +239,8 @@ public final class ResourceHelper {
} catch (NumberFormatException e) {
// we'll return null below.
Bridge.getLog().error(LayoutLog.TAG_RESOURCES_FORMAT,
- "Failed to convert " + stringValue + " into a drawable", e);
+ "Failed to convert " + stringValue + " into a drawable", e,
+ null /*data*/);
}
}
}